openscad-cpp-evaluator 0.29.2__tar.gz → 0.30.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/CLAUDE.md +23 -1
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/PKG-INFO +1 -1
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/dispatch.hpp +19 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/eval_error.hpp +35 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/pyproject.toml +1 -1
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/builtins/function_builtins.cpp +13 -0
- openscad_cpp_evaluator-0.30.0/src/builtins/registry.cpp +142 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/bytecode_vm.cpp +20 -6
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/csg_resolve.cpp +1 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/eval_error.cpp +37 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/user_calls.cpp +8 -1
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/CMakeLists.txt +1 -0
- openscad_cpp_evaluator-0.30.0/tests/test_unexpected_args.cpp +151 -0
- openscad_cpp_evaluator-0.29.2/src/builtins/registry.cpp +0 -81
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/.github/workflows/wheels.yml +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/.gitignore +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/.gitmodules +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/LICENSE +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/README.md +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/bindings/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/bindings/ast_to_py.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/bindings/module.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/cmake/embed_font.cmake +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/examples/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/examples/eval_perf_benchmark.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/examples/manifold_cache_reuse.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/examples/minimal_debugger.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/.gitignore +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/README.md +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/src/api.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/src/comments.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/src/position.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/src/scope.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/bytecode.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/bytecode_vm.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/colored_body.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/evaluator.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/export.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/mesh_check.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/profile.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/scope_trail.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/segments.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/stb_font_provider.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/value.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/python/openscad_cpp_evaluator/__init__.py +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/resources/fonts/LICENSE +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/resources/fonts/LiberationSans-Regular.ttf +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/builtins/booleans.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/builtins/builtins.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/builtins/call_args.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/builtins/color.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/builtins/control.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/builtins/extrude.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/builtins/import.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/builtins/modifiers.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/builtins/primitives_2d.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/builtins/primitives_3d.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/builtins/roof.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/builtins/segments.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/builtins/surface.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/builtins/text.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/builtins/topology.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/builtins/transforms.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/colored_body.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/csg_generate.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/css_colors.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/debug/debug_repl.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/debug_profile.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/eval_context.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/eval_use.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/export.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/import/dxf_import.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/import/mesh_import.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/import/surface_load.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/import/svg_import.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/stmt_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/text/stb_font_provider.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/text/text_metrics.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/value.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_booleans.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_cli.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_control_flow.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_csg_tree.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_debug_hooks.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_dxf_svg_import.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_eval_context.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_export.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_extrude_roof.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_import_export.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_multi_color_merge.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_primitives.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_profiling.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_python_bindings.py +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_scope_trail.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_scoping.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_surface.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_tail_calls.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_text.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_transforms.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_use.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_value.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_viewport_params.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tests/test_zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tools/cli/cli_lib.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tools/cli/cli_lib.hpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/uv.lock +0 -0
|
@@ -424,7 +424,29 @@ grep for `ponytail:`.
|
|
|
424
424
|
give sibling statements in the same block correct assignment visibility (see the header comment
|
|
425
425
|
before reworking this; it's not an arbitrary choice).
|
|
426
426
|
- `include/openscad_cpp_evaluator/eval_error.hpp`, `src/eval_error.cpp` — `EvalError` and the
|
|
427
|
-
exact ERROR/TRACE string formatting real OpenSCAD produces.
|
|
427
|
+
exact ERROR/TRACE string formatting real OpenSCAD produces. Also the **unexpected-argument
|
|
428
|
+
warnings** (`warnUnexpectedNamedArg`/`warnTooManyPositionalArgs`/`warnUnexpectedArgs`), the port
|
|
429
|
+
of real OpenSCAD's `Parameters.cc` `parse_without_defaults`: `variable X not specified as
|
|
430
|
+
parameter` for a named argument the callee doesn't declare, and `Too many unnamed arguments
|
|
431
|
+
supplied` once per call for positional arguments past the last parameter. `$`-prefixed names
|
|
432
|
+
other than `$children` are exempt (`isConfigVariable`, mirroring
|
|
433
|
+
`ContextFrame::is_config_variable` — a `$`-name is a dynamic-scope override, never a parameter).
|
|
434
|
+
The check has to be repeated at **every** argument-binding path, since there are five and none of
|
|
435
|
+
them share a choke point: `bindArgs` (interpreter, `user_calls.cpp`),
|
|
436
|
+
`buildBoundArgs`/`bindAstArgsIntoFrame` (bytecode VM, `bytecode_vm.cpp`), `evalModularCall`
|
|
437
|
+
(builtin modules, `csg_resolve.cpp`) and the VM's own `Op::PushBuiltinWrap`/`Op::PushCsgWrap`
|
|
438
|
+
handlers — the transform/color/hull/minkowski/render/extrude/projection/offset/roof/CSG family
|
|
439
|
+
bypasses `evalModularCall` entirely once compiled, which is exactly the gap
|
|
440
|
+
`tests/test_unexpected_args.cpp` runs every case twice (VM off and on) to catch. Builtin
|
|
441
|
+
parameter names live in `builtinParamNames` (`registry.cpp`): each list is the union of real
|
|
442
|
+
OpenSCAD's own `Parameters::parse` declaration and any extra name this port reads via `getArg`,
|
|
443
|
+
so the port never warns about an argument it goes on to honour — **add to it whenever a builtin
|
|
444
|
+
gains a parameter**, or that parameter starts warning. Builtin *functions* deliberately have no
|
|
445
|
+
entries beyond `textmetrics`/`fontmetrics`: upstream reads their arguments positionally without
|
|
446
|
+
`Parameters::parse`, so `sin(bogus=30)` warns about nothing there (verified against 2022.08.22)
|
|
447
|
+
and warning here would be a divergence. Not ported: the reference's `argument X supplied more
|
|
448
|
+
than once` / `argument X overrides positional argument`, separate conditions this port's simpler
|
|
449
|
+
positional-matching rule doesn't track.
|
|
428
450
|
- `include/openscad_cpp_evaluator/evaluator.hpp`, `src/expr_eval.cpp`, `src/stmt_eval.cpp`,
|
|
429
451
|
`src/user_calls.cpp` — the `Evaluator` class. Expression/statement dispatch is a `switch` on
|
|
430
452
|
`NodeKind` (matches `openscad_cpp_parser`'s own dispatch convention, not a visitor).
|
|
@@ -54,6 +54,25 @@ using GenerateFn = std::vector<ColoredBody> (*)(Evaluator&, const CSGParams&, co
|
|
|
54
54
|
const std::unordered_map<std::string_view, ResolveFn>& resolveDispatch();
|
|
55
55
|
const std::unordered_map<std::string_view, GenerateFn>& generateDispatch();
|
|
56
56
|
|
|
57
|
+
// Every parameter name a builtin accepts, for the unexpected-argument
|
|
58
|
+
// warning (see eval_error.hpp). Returns nullptr for a name with no entry,
|
|
59
|
+
// which suppresses the check rather than warning about everything.
|
|
60
|
+
//
|
|
61
|
+
// Each list is the UNION of real OpenSCAD's own Parameters::parse
|
|
62
|
+
// declaration for that builtin (2022.08.22 -- the authority on what warns
|
|
63
|
+
// upstream) and any extra name this port itself reads via getArg, so this
|
|
64
|
+
// port never warns about an argument it goes on to honour.
|
|
65
|
+
const std::vector<std::string>* builtinParamNames(const std::string& name);
|
|
66
|
+
|
|
67
|
+
// builtinParamNames + warnUnexpectedArgs for one builtin module call. Must
|
|
68
|
+
// be invoked from EVERY path a builtin call can take: evalModularCall
|
|
69
|
+
// (interpreter, and Op::NativeStatement) plus the bytecode VM's own
|
|
70
|
+
// Op::PushBuiltinWrap/Op::PushCsgWrap handlers, which bypass
|
|
71
|
+
// evalModularCall entirely for the transform/color/hull/extrude/CSG family.
|
|
72
|
+
// Silently does nothing for a node that isn't a ModularCall (a `#`/`%`/`!`
|
|
73
|
+
// modifier shares BuiltinWrapSite but carries no arguments).
|
|
74
|
+
void warnUnexpectedBuiltinArgs(Evaluator& ev, const oscad::ASTNode& callNode);
|
|
75
|
+
|
|
57
76
|
// Concatenates every top-level node's already-generated `.bodies` (does NOT
|
|
58
77
|
// recurse into `.children` -- a parent's `.bodies` is already the fully
|
|
59
78
|
// combined result of its children). Mirrors the reference's
|
|
@@ -2,12 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
#include "openscad_cpp_parser/position.hpp"
|
|
4
4
|
|
|
5
|
+
#include <memory>
|
|
5
6
|
#include <stdexcept>
|
|
6
7
|
#include <string>
|
|
7
8
|
#include <vector>
|
|
8
9
|
|
|
9
10
|
namespace oscad {
|
|
10
11
|
class ASTNode;
|
|
12
|
+
class Argument;
|
|
13
|
+
class ParameterDeclaration;
|
|
11
14
|
} // namespace oscad
|
|
12
15
|
|
|
13
16
|
namespace oscadeval {
|
|
@@ -129,4 +132,36 @@ std::string formatError(const std::string& msg, const oscad::Position* nodePosit
|
|
|
129
132
|
std::string formatWarning(const std::string& msg, const oscad::Position* nodePosition,
|
|
130
133
|
const std::vector<CallStackFrame>& callStack);
|
|
131
134
|
|
|
135
|
+
// -- Unexpected-argument warnings -----------------------------------------
|
|
136
|
+
//
|
|
137
|
+
// Real OpenSCAD (Parameters.cc's parse_without_defaults) warns for a named
|
|
138
|
+
// argument the callee doesn't declare, and once per call for positional
|
|
139
|
+
// arguments past the last parameter. Both are silently dropped otherwise,
|
|
140
|
+
// which makes a typo'd argument name invisible -- the call still runs, the
|
|
141
|
+
// parameter just keeps its default. Wording is verbatim from the reference
|
|
142
|
+
// (2022.08.22, which quotes neither name nor message).
|
|
143
|
+
//
|
|
144
|
+
// NOT covered here (separate reference warnings, separate conditions):
|
|
145
|
+
// "argument X supplied more than once" and "argument X overrides positional
|
|
146
|
+
// argument".
|
|
147
|
+
class Evaluator;
|
|
148
|
+
|
|
149
|
+
// ContextFrame::is_config_variable: a $-prefixed name other than $children
|
|
150
|
+
// is a dynamic-scope override, never a declared parameter, so it is exempt.
|
|
151
|
+
bool isConfigVariable(const std::string& name);
|
|
152
|
+
|
|
153
|
+
// Linear scan -- ponytail: parameter lists are single-digit in practice, so
|
|
154
|
+
// a per-call set/map would cost more than it saves.
|
|
155
|
+
bool declaresParam(const std::vector<std::unique_ptr<oscad::ParameterDeclaration>>& params, const std::string& name);
|
|
156
|
+
|
|
157
|
+
void warnUnexpectedNamedArg(Evaluator& ev, const std::string& name, const oscad::Position* pos);
|
|
158
|
+
void warnTooManyPositionalArgs(Evaluator& ev, const oscad::Position* pos);
|
|
159
|
+
|
|
160
|
+
// Both warnings at once for a callee whose parameter names are a fixed list
|
|
161
|
+
// rather than a declaration -- i.e. a builtin (see builtinParamNames,
|
|
162
|
+
// dispatch.hpp). Reports against each argument's own position, which is the
|
|
163
|
+
// call's own line in every case that isn't a multi-line argument list.
|
|
164
|
+
void warnUnexpectedArgs(Evaluator& ev, const std::vector<std::string>& params,
|
|
165
|
+
const std::vector<std::unique_ptr<oscad::Argument>>& arguments);
|
|
166
|
+
|
|
132
167
|
} // namespace oscadeval
|
{openscad_cpp_evaluator-0.29.2 → openscad_cpp_evaluator-0.30.0}/src/builtins/function_builtins.cpp
RENAMED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#include "openscad_cpp_evaluator/function_builtins.hpp"
|
|
2
2
|
|
|
3
|
+
#include "openscad_cpp_evaluator/dispatch.hpp"
|
|
3
4
|
#include "openscad_cpp_evaluator/evaluator.hpp"
|
|
4
5
|
#include "openscad_cpp_evaluator/segments.hpp"
|
|
5
6
|
#include "openscad_cpp_evaluator/text_metrics.hpp"
|
|
@@ -509,6 +510,18 @@ Value evalBuiltinFunction(Evaluator& ev, const std::string& name, const CallArgs
|
|
|
509
510
|
// elsewhere before reaching here) -- mirrors the old chain's fallthrough.
|
|
510
511
|
if (idIt == ids.end()) return Value{};
|
|
511
512
|
|
|
513
|
+
// Only textmetrics/fontmetrics have an entry -- every other builtin
|
|
514
|
+
// function reads its arguments positionally upstream and warns about
|
|
515
|
+
// nothing. See builtinParamNames (registry.cpp).
|
|
516
|
+
if (const std::vector<std::string>* declared = builtinParamNames(name)) {
|
|
517
|
+
for (const auto& [argName, _] : args.named) {
|
|
518
|
+
if (!isConfigVariable(argName) &&
|
|
519
|
+
std::find(declared->begin(), declared->end(), argName) == declared->end()) {
|
|
520
|
+
warnUnexpectedNamedArg(ev, argName, &node.position());
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
512
525
|
if (const auto arityIt = scalarNumericArity().find(name); arityIt != scalarNumericArity().end()) {
|
|
513
526
|
const std::vector<Value> positional = allPositional(args);
|
|
514
527
|
if (positional.size() < arityIt->second) return Value{};
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#include "builtins.hpp"
|
|
2
|
+
|
|
3
|
+
#include "openscad_cpp_evaluator/dispatch.hpp"
|
|
4
|
+
#include "openscad_cpp_evaluator/eval_error.hpp"
|
|
5
|
+
|
|
6
|
+
namespace oscadeval {
|
|
7
|
+
|
|
8
|
+
const std::unordered_map<std::string_view, ResolveFn>& resolveDispatch() {
|
|
9
|
+
static const std::unordered_map<std::string_view, ResolveFn> table = {
|
|
10
|
+
{"cube", &resolveCube},
|
|
11
|
+
{"sphere", &resolveSphere},
|
|
12
|
+
{"cylinder", &resolveCylinder},
|
|
13
|
+
{"polyhedron", &resolvePolyhedron},
|
|
14
|
+
{"circle", &resolve2d},
|
|
15
|
+
{"square", &resolve2d},
|
|
16
|
+
{"polygon", &resolve2d},
|
|
17
|
+
{"translate", &resolveTransform},
|
|
18
|
+
{"rotate", &resolveTransform},
|
|
19
|
+
{"scale", &resolveTransform},
|
|
20
|
+
{"mirror", &resolveTransform},
|
|
21
|
+
{"multmatrix", &resolveTransform},
|
|
22
|
+
{"resize", &resolveTransform},
|
|
23
|
+
{"color", &resolveColor},
|
|
24
|
+
{"union", &resolveCsg},
|
|
25
|
+
{"difference", &resolveCsg},
|
|
26
|
+
{"intersection", &resolveCsg},
|
|
27
|
+
{"children", &resolveChildren},
|
|
28
|
+
{"render", &resolveRender},
|
|
29
|
+
{"breakpoint", &resolveBreakpoint},
|
|
30
|
+
{"import", &resolveImport},
|
|
31
|
+
{"hull", &resolveHull},
|
|
32
|
+
{"minkowski", &resolveMinkowski},
|
|
33
|
+
{"linear_extrude", &resolveLinearExtrude},
|
|
34
|
+
{"rotate_extrude", &resolveRotateExtrude},
|
|
35
|
+
{"projection", &resolveProjection},
|
|
36
|
+
{"roof", &resolveRoof},
|
|
37
|
+
{"offset", &resolveOffset},
|
|
38
|
+
{"surface", &resolveSurface},
|
|
39
|
+
{"text", &resolveText},
|
|
40
|
+
};
|
|
41
|
+
return table;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const std::unordered_map<std::string_view, GenerateFn>& generateDispatch() {
|
|
45
|
+
static const std::unordered_map<std::string_view, GenerateFn> table = {
|
|
46
|
+
{"cube", &generateCube},
|
|
47
|
+
{"sphere", &generateSphere},
|
|
48
|
+
{"cylinder", &generateCylinder},
|
|
49
|
+
{"polyhedron", &generatePolyhedron},
|
|
50
|
+
{"circle", &generate2d},
|
|
51
|
+
{"square", &generate2d},
|
|
52
|
+
{"polygon", &generate2d},
|
|
53
|
+
{"translate", &generateTransform},
|
|
54
|
+
{"rotate", &generateTransform},
|
|
55
|
+
{"scale", &generateTransform},
|
|
56
|
+
{"mirror", &generateTransform},
|
|
57
|
+
{"multmatrix", &generateTransform},
|
|
58
|
+
{"resize", &generateTransform},
|
|
59
|
+
{"color", &generateColor},
|
|
60
|
+
{"union", &generateCsg},
|
|
61
|
+
{"difference", &generateCsg},
|
|
62
|
+
{"intersection", &generateCsg},
|
|
63
|
+
{"highlight", &generateHighlight},
|
|
64
|
+
{"background", &generateBackground},
|
|
65
|
+
{"show_only", &generateShowOnly},
|
|
66
|
+
{"children", &generateChildren},
|
|
67
|
+
{"intersection_for", &generateIntersectionFor},
|
|
68
|
+
{"import", &generateImport},
|
|
69
|
+
{"hull", &generateHull},
|
|
70
|
+
{"minkowski", &generateMinkowski},
|
|
71
|
+
{"linear_extrude", &generateLinearExtrude},
|
|
72
|
+
{"rotate_extrude", &generateRotateExtrude},
|
|
73
|
+
{"projection", &generateProjection},
|
|
74
|
+
{"roof", &generateRoof},
|
|
75
|
+
{"offset", &generateOffset},
|
|
76
|
+
{"surface", &generateSurface},
|
|
77
|
+
{"text", &generateText},
|
|
78
|
+
};
|
|
79
|
+
return table;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const std::vector<std::string>* builtinParamNames(const std::string& name) {
|
|
83
|
+
// Deliberately absent: the builtin *functions* other than the three
|
|
84
|
+
// below. Real OpenSCAD's builtin functions read their arguments
|
|
85
|
+
// positionally without going through Parameters::parse, so `sin(bogus=30)`
|
|
86
|
+
// warns about nothing upstream -- verified against 2022.08.22 -- and
|
|
87
|
+
// warning here would be a divergence, not a fix.
|
|
88
|
+
static const std::unordered_map<std::string, std::vector<std::string>> table = {
|
|
89
|
+
// -- builtin modules ---------------------------------------------
|
|
90
|
+
{"cube", {"size", "center"}},
|
|
91
|
+
{"sphere", {"r", "d"}},
|
|
92
|
+
{"cylinder", {"h", "r1", "r2", "center", "r", "d", "d1", "d2"}},
|
|
93
|
+
{"polyhedron", {"points", "faces", "convexity", "triangles"}},
|
|
94
|
+
{"square", {"size", "center"}},
|
|
95
|
+
{"circle", {"r", "d"}},
|
|
96
|
+
{"polygon", {"points", "paths", "convexity"}},
|
|
97
|
+
{"translate", {"v"}},
|
|
98
|
+
{"rotate", {"a", "v"}},
|
|
99
|
+
{"scale", {"v"}},
|
|
100
|
+
{"mirror", {"v"}},
|
|
101
|
+
{"multmatrix", {"m"}},
|
|
102
|
+
{"resize", {"newsize", "auto", "convexity"}},
|
|
103
|
+
{"color", {"c", "alpha"}},
|
|
104
|
+
{"union", {}},
|
|
105
|
+
{"difference", {}},
|
|
106
|
+
{"intersection", {}},
|
|
107
|
+
{"hull", {}},
|
|
108
|
+
{"minkowski", {"convexity"}},
|
|
109
|
+
{"children", {"index"}},
|
|
110
|
+
{"render", {"convexity"}},
|
|
111
|
+
// "repair" is this port's own addition, not an upstream parameter.
|
|
112
|
+
{"import",
|
|
113
|
+
{"file", "layer", "convexity", "origin", "scale", "width", "height", "filename", "layername", "center", "dpi",
|
|
114
|
+
"id", "repair"}},
|
|
115
|
+
{"linear_extrude", {"height", "v", "scale", "center", "twist", "slices", "segments", "convexity"}},
|
|
116
|
+
{"rotate_extrude", {"angle", "start", "convexity"}},
|
|
117
|
+
{"projection", {"cut", "convexity"}},
|
|
118
|
+
{"roof", {"method", "convexity"}},
|
|
119
|
+
{"offset", {"r", "delta", "chamfer"}},
|
|
120
|
+
{"surface", {"file", "center", "convexity", "invert"}},
|
|
121
|
+
{"text", {"text", "size", "font", "direction", "language", "script", "halign", "valign", "spacing"}},
|
|
122
|
+
// breakpoint() is this port's own debugger extension, no upstream
|
|
123
|
+
// equivalent to mirror.
|
|
124
|
+
{"breakpoint", {"condition"}},
|
|
125
|
+
|
|
126
|
+
// -- the three builtin FUNCTIONS that do use Parameters::parse ----
|
|
127
|
+
{"textmetrics", {"text", "size", "font", "direction", "language", "script", "halign", "valign", "spacing"}},
|
|
128
|
+
{"fontmetrics", {"size", "font"}},
|
|
129
|
+
};
|
|
130
|
+
auto it = table.find(name);
|
|
131
|
+
return it == table.end() ? nullptr : &it->second;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
void warnUnexpectedBuiltinArgs(Evaluator& ev, const oscad::ASTNode& callNode) {
|
|
135
|
+
if (callNode.kind() != oscad::NodeKind::ModularCall) return;
|
|
136
|
+
const auto& call = static_cast<const oscad::ModularCall&>(callNode);
|
|
137
|
+
if (const std::vector<std::string>* declared = builtinParamNames(call.name->name)) {
|
|
138
|
+
warnUnexpectedArgs(ev, *declared, call.arguments);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
} // namespace oscadeval
|
|
@@ -40,18 +40,25 @@ CallArgs buildCallArgs(const CompiledChunk::CallSite& site, std::vector<Value>&
|
|
|
40
40
|
// LIST is `paramNames` (in declared order -- a FunctionDeclaration's
|
|
41
41
|
// parameters or a FunctionLiteral's). Shared by CallFn/CallFnTail (a
|
|
42
42
|
// site.decl callee) and CallDynamic/CallDynamicTail (a closure callee).
|
|
43
|
-
BoundArgs buildBoundArgs(const CompiledChunk::CallSite& site, std::vector<Value>& args, size_t argCount,
|
|
43
|
+
BoundArgs buildBoundArgs(Evaluator& ev, const CompiledChunk::CallSite& site, std::vector<Value>& args, size_t argCount,
|
|
44
44
|
const std::vector<std::unique_ptr<oscad::ParameterDeclaration>>& paramNames) {
|
|
45
45
|
BoundArgs bound;
|
|
46
46
|
bound.reserve(argCount);
|
|
47
47
|
size_t positionalIdx = 0;
|
|
48
48
|
const size_t nparams = paramNames.size();
|
|
49
|
+
const oscad::Position* pos = site.callNode ? &site.callNode->position() : nullptr;
|
|
49
50
|
for (size_t i = 0; i < argCount; ++i) {
|
|
50
51
|
if (site.argNames[i]) {
|
|
51
|
-
|
|
52
|
+
const std::string& name = *site.argNames[i];
|
|
53
|
+
if (!isConfigVariable(name) && !declaresParam(paramNames, name)) {
|
|
54
|
+
warnUnexpectedNamedArg(ev, name, pos);
|
|
55
|
+
}
|
|
56
|
+
bound.set(name, std::move(args[i]));
|
|
52
57
|
} else {
|
|
53
58
|
if (positionalIdx < nparams) {
|
|
54
59
|
bound.set(paramNames[positionalIdx]->name->name, std::move(args[i]));
|
|
60
|
+
} else if (positionalIdx == nparams) {
|
|
61
|
+
warnTooManyPositionalArgs(ev, pos);
|
|
55
62
|
}
|
|
56
63
|
++positionalIdx;
|
|
57
64
|
}
|
|
@@ -126,6 +133,9 @@ void bindAstArgsIntoFrame(Evaluator& ev, const CompiledChunk& chunk,
|
|
|
126
133
|
if (!matched && !name.empty() && name[0] == '$') {
|
|
127
134
|
ctx.dyn->set(name, v);
|
|
128
135
|
}
|
|
136
|
+
if (!matched && !isConfigVariable(name)) {
|
|
137
|
+
warnUnexpectedNamedArg(ev, name, &argPtr->position());
|
|
138
|
+
}
|
|
129
139
|
} else {
|
|
130
140
|
auto& a = static_cast<const oscad::PositionalArgument&>(*argPtr);
|
|
131
141
|
Value v = ev.evalExpr(*a.expr, callerCtx);
|
|
@@ -137,6 +147,8 @@ void bindAstArgsIntoFrame(Evaluator& ev, const CompiledChunk& chunk,
|
|
|
137
147
|
frame.slots[static_cast<size_t>(p.slot)] = std::move(v);
|
|
138
148
|
}
|
|
139
149
|
frame.bound[positionalIdx] = true;
|
|
150
|
+
} else if (positionalIdx == nparams) {
|
|
151
|
+
warnTooManyPositionalArgs(ev, &argPtr->position());
|
|
140
152
|
}
|
|
141
153
|
++positionalIdx;
|
|
142
154
|
}
|
|
@@ -770,7 +782,7 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
770
782
|
f.stack.push_back(evalBuiltinFunction(ev, site.calleeName, callArgs, *site.callNode));
|
|
771
783
|
++f.pc;
|
|
772
784
|
} else {
|
|
773
|
-
BoundArgs bound = buildBoundArgs(site, args, argCount, site.decl->parameters);
|
|
785
|
+
BoundArgs bound = buildBoundArgs(ev, site, args, argCount, site.decl->parameters);
|
|
774
786
|
const CompiledChunk* calleeChunk = ev.useBytecodeVm() ? ev.lookupOrCompileChunk(*site.decl) : nullptr;
|
|
775
787
|
if (calleeChunk) {
|
|
776
788
|
const oscad::Scope* fnScope = site.decl->scope() ? site.decl->scope() : ctx.scope;
|
|
@@ -801,7 +813,7 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
801
813
|
if (const auto* closurePtr = std::get_if<ClosurePtr>(&callee); closurePtr && *closurePtr) {
|
|
802
814
|
const Closure& closure = **closurePtr;
|
|
803
815
|
const oscad::FunctionLiteral& funcNode = *closure.node;
|
|
804
|
-
BoundArgs bound = buildBoundArgs(site, args, argCount, funcNode.parameters);
|
|
816
|
+
BoundArgs bound = buildBoundArgs(ev, site, args, argCount, funcNode.parameters);
|
|
805
817
|
const CompiledChunk* calleeChunk = ev.useBytecodeVm() ? ev.lookupCompiledLiteralChunk(funcNode) : nullptr;
|
|
806
818
|
if (calleeChunk) {
|
|
807
819
|
const oscad::Scope* fnScope = funcNode.scope() ? funcNode.scope() : ctx.scope;
|
|
@@ -827,7 +839,7 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
827
839
|
args[argCount - 1 - i] = std::move(f.stack.back());
|
|
828
840
|
f.stack.pop_back();
|
|
829
841
|
}
|
|
830
|
-
BoundArgs bound = buildBoundArgs(site, args, argCount, site.decl->parameters);
|
|
842
|
+
BoundArgs bound = buildBoundArgs(ev, site, args, argCount, site.decl->parameters);
|
|
831
843
|
// Tail-hop-in-place requires f.hopEligible -- a frame
|
|
832
844
|
// that's call-boundary-free (statement expression,
|
|
833
845
|
// assignment block, parameter default) has no
|
|
@@ -894,7 +906,7 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
894
906
|
if (const auto* closurePtr = std::get_if<ClosurePtr>(&callee); closurePtr && *closurePtr) {
|
|
895
907
|
const Closure& closure = **closurePtr;
|
|
896
908
|
const oscad::FunctionLiteral& funcNode = *closure.node;
|
|
897
|
-
BoundArgs bound = buildBoundArgs(site, args, argCount, funcNode.parameters);
|
|
909
|
+
BoundArgs bound = buildBoundArgs(ev, site, args, argCount, funcNode.parameters);
|
|
898
910
|
const bool thisFrameBracketed = f.hopEligible;
|
|
899
911
|
std::optional<EvalContext> hopCtx = thisFrameBracketed
|
|
900
912
|
? ev.isolatedCallCtxFor(funcNode, ctx, capturedLetTrail(closure))
|
|
@@ -1055,6 +1067,7 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
1055
1067
|
// uncacheable/ManifoldCache taint tracking for a
|
|
1056
1068
|
// rands() call embedded in the wrapper's own args).
|
|
1057
1069
|
const std::uint64_t randsBefore = ev.randsCallCount();
|
|
1070
|
+
warnUnexpectedBuiltinArgs(ev, *site.node);
|
|
1058
1071
|
CSGParams params;
|
|
1059
1072
|
CallArgs deferredArgs; // Roof only -- see PendingBuiltinWrap's own doc comment
|
|
1060
1073
|
switch (site.kind) {
|
|
@@ -1183,6 +1196,7 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
1183
1196
|
// rands-in-args taint reasoning as Op::PushBuiltinWrap.
|
|
1184
1197
|
const std::uint64_t randsBefore = ev.randsCallCount();
|
|
1185
1198
|
if (site.hasArgs) {
|
|
1199
|
+
warnUnexpectedBuiltinArgs(ev, *site.node);
|
|
1186
1200
|
// union/difference/intersection take no positional
|
|
1187
1201
|
// arguments in real OpenSCAD -- `args` is discarded,
|
|
1188
1202
|
// exactly mirroring resolveCsg's own `(void)args;`
|
|
@@ -94,6 +94,7 @@ void Evaluator::evalModularCall(const oscad::ModularCall& node, EvalContext& ctx
|
|
|
94
94
|
CSGParams params;
|
|
95
95
|
try {
|
|
96
96
|
if (hasResolveFn) {
|
|
97
|
+
warnUnexpectedBuiltinArgs(*this, node);
|
|
97
98
|
params = it->second(*this, node, ctx);
|
|
98
99
|
} else if (!isBuiltin) {
|
|
99
100
|
evalUserModule(static_cast<const oscad::ModuleDeclaration&>(*userModuleDecl), node, ctx);
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
#include "openscad_cpp_evaluator/evaluator.hpp"
|
|
4
4
|
|
|
5
|
+
#include <algorithm>
|
|
6
|
+
|
|
5
7
|
namespace oscadeval {
|
|
6
8
|
|
|
7
9
|
void Evaluator::error(const std::string& msg, const oscad::ASTNode& node, const std::string& innermostFrame) {
|
|
@@ -122,4 +124,39 @@ std::string formatWarning(const std::string& msg, const oscad::Position* nodePos
|
|
|
122
124
|
return full;
|
|
123
125
|
}
|
|
124
126
|
|
|
127
|
+
bool isConfigVariable(const std::string& name) {
|
|
128
|
+
return !name.empty() && name[0] == '$' && name != "$children";
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
bool declaresParam(const std::vector<std::unique_ptr<oscad::ParameterDeclaration>>& params, const std::string& name) {
|
|
132
|
+
for (const auto& p : params) {
|
|
133
|
+
if (p->name->name == name) return true;
|
|
134
|
+
}
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
void warnUnexpectedNamedArg(Evaluator& ev, const std::string& name, const oscad::Position* pos) {
|
|
139
|
+
ev.warn("variable " + name + " not specified as parameter", pos);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
void warnTooManyPositionalArgs(Evaluator& ev, const oscad::Position* pos) {
|
|
143
|
+
ev.warn("Too many unnamed arguments supplied", pos);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
void warnUnexpectedArgs(Evaluator& ev, const std::vector<std::string>& params,
|
|
147
|
+
const std::vector<std::unique_ptr<oscad::Argument>>& arguments) {
|
|
148
|
+
size_t positionalIdx = 0;
|
|
149
|
+
for (const auto& argPtr : arguments) {
|
|
150
|
+
if (argPtr->kind() == oscad::NodeKind::NamedArgument) {
|
|
151
|
+
const std::string& name = static_cast<const oscad::NamedArgument&>(*argPtr).name->name;
|
|
152
|
+
if (!isConfigVariable(name) &&
|
|
153
|
+
std::find(params.begin(), params.end(), name) == params.end()) {
|
|
154
|
+
warnUnexpectedNamedArg(ev, name, &argPtr->position());
|
|
155
|
+
}
|
|
156
|
+
} else if (positionalIdx++ == params.size()) {
|
|
157
|
+
warnTooManyPositionalArgs(ev, &argPtr->position());
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
125
162
|
} // namespace oscadeval
|
|
@@ -191,11 +191,18 @@ BoundArgs Evaluator::bindArgs(const std::vector<std::unique_ptr<oscad::Parameter
|
|
|
191
191
|
for (const auto& argPtr : arguments) {
|
|
192
192
|
if (argPtr->kind() == oscad::NodeKind::NamedArgument) {
|
|
193
193
|
auto& a = static_cast<const oscad::NamedArgument&>(*argPtr);
|
|
194
|
-
|
|
194
|
+
const std::string& name = a.name->name;
|
|
195
|
+
if (!isConfigVariable(name) && !declaresParam(params, name)) {
|
|
196
|
+
warnUnexpectedNamedArg(*this, name, &argPtr->position());
|
|
197
|
+
}
|
|
198
|
+
result.set(name, evalExprMaybeCompiled(*a.expr, ctx));
|
|
195
199
|
} else {
|
|
196
200
|
auto& a = static_cast<const oscad::PositionalArgument&>(*argPtr);
|
|
197
201
|
if (positionalIdx < nparams) {
|
|
198
202
|
result.set(params[positionalIdx]->name->name, evalExprMaybeCompiled(*a.expr, ctx));
|
|
203
|
+
} else if (positionalIdx == nparams) {
|
|
204
|
+
// Once per call, like the reference's warned_for_extra_arguments.
|
|
205
|
+
warnTooManyPositionalArgs(*this, &argPtr->position());
|
|
199
206
|
}
|
|
200
207
|
++positionalIdx;
|
|
201
208
|
}
|
|
@@ -35,6 +35,7 @@ add_executable(oscad_eval_tests
|
|
|
35
35
|
test_debug_hooks.cpp
|
|
36
36
|
test_multi_color_merge.cpp
|
|
37
37
|
test_viewport_params.cpp
|
|
38
|
+
test_unexpected_args.cpp
|
|
38
39
|
test_cli.cpp
|
|
39
40
|
)
|
|
40
41
|
target_link_libraries(oscad_eval_tests PRIVATE openscad_cpp_evaluator oscad_cli_lib GTest::gtest_main)
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
#include "openscad_cpp_evaluator/evaluator.hpp"
|
|
2
|
+
|
|
3
|
+
#include "test_helpers.hpp"
|
|
4
|
+
|
|
5
|
+
#include <gtest/gtest.h>
|
|
6
|
+
|
|
7
|
+
// Real OpenSCAD (Parameters.cc's parse_without_defaults) warns for a named
|
|
8
|
+
// argument the callee doesn't declare, and once per call for positional
|
|
9
|
+
// arguments past the last parameter. Every expectation below was checked
|
|
10
|
+
// against a real OpenSCAD 2022.08.22 run of the same script -- same message
|
|
11
|
+
// text, same set of calls warned about.
|
|
12
|
+
//
|
|
13
|
+
// Every case runs twice, VM off and VM on: user calls bind through
|
|
14
|
+
// bindArgs (interpreter) or buildBoundArgs/bindAstArgsIntoFrame (VM), and
|
|
15
|
+
// the transform/color/hull/extrude/CSG builtins bypass evalModularCall
|
|
16
|
+
// entirely once compiled (Op::PushBuiltinWrap/Op::PushCsgWrap). Any of those
|
|
17
|
+
// paths missing the check is exactly the bug this file exists to catch.
|
|
18
|
+
using namespace oscadeval;
|
|
19
|
+
using namespace oscadeval::test;
|
|
20
|
+
|
|
21
|
+
namespace {
|
|
22
|
+
|
|
23
|
+
class ScopedVm {
|
|
24
|
+
public:
|
|
25
|
+
explicit ScopedVm(bool enabled) { Evaluator::setBytecodeVmEnabledForTesting(enabled); }
|
|
26
|
+
~ScopedVm() { Evaluator::setBytecodeVmEnabledForTesting(std::nullopt); }
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
std::vector<std::string> warningsFor(const std::string& code) {
|
|
30
|
+
std::vector<std::string> out;
|
|
31
|
+
Evaluated e = evalSrc(code, [&](const std::string& msg) {
|
|
32
|
+
if (msg.rfind("WARNING: ", 0) == 0) out.push_back(msg);
|
|
33
|
+
});
|
|
34
|
+
(void)e;
|
|
35
|
+
return out;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Every warning line, both VM settings, asserted to be identical between
|
|
39
|
+
// them -- the two binding paths must not disagree about what is unexpected.
|
|
40
|
+
std::vector<std::string> warningsBothPaths(const std::string& code) {
|
|
41
|
+
std::vector<std::string> interpreted;
|
|
42
|
+
{
|
|
43
|
+
ScopedVm vm(false);
|
|
44
|
+
interpreted = warningsFor(code);
|
|
45
|
+
}
|
|
46
|
+
std::vector<std::string> compiled;
|
|
47
|
+
{
|
|
48
|
+
ScopedVm vm(true);
|
|
49
|
+
compiled = warningsFor(code);
|
|
50
|
+
}
|
|
51
|
+
EXPECT_EQ(interpreted, compiled) << "VM-on and VM-off disagree for: " << code;
|
|
52
|
+
return interpreted;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// True if some warning contains `needle`.
|
|
56
|
+
bool has(const std::vector<std::string>& warnings, const std::string& needle) {
|
|
57
|
+
for (const std::string& w : warnings) {
|
|
58
|
+
if (w.find(needle) != std::string::npos) return true;
|
|
59
|
+
}
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
} // namespace
|
|
64
|
+
|
|
65
|
+
TEST(UnexpectedArgs, UserModuleNamedArgNotAParameter) {
|
|
66
|
+
auto w = warningsBothPaths("module m(a=1) { } m(a=2, b=3);");
|
|
67
|
+
ASSERT_EQ(w.size(), 1u);
|
|
68
|
+
EXPECT_NE(w[0].find("WARNING: variable b not specified as parameter"), std::string::npos);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
TEST(UnexpectedArgs, UserFunctionNamedArgNotAParameter) {
|
|
72
|
+
auto w = warningsBothPaths("function f(x=1) = x; echo(f(x=2, y=3));");
|
|
73
|
+
ASSERT_EQ(w.size(), 1u);
|
|
74
|
+
EXPECT_NE(w[0].find("WARNING: variable y not specified as parameter"), std::string::npos);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// A call from inside another function is the case the bytecode VM's own
|
|
78
|
+
// Op::CallFn path (buildBoundArgs) handles, distinct from the top-level
|
|
79
|
+
// entry (bindAstArgsIntoFrame).
|
|
80
|
+
TEST(UnexpectedArgs, NestedUserFunctionCallStillWarns) {
|
|
81
|
+
auto w = warningsBothPaths("function inner(n=1) = n; function outer(k) = inner(n=k, bogus=1); echo(outer(2));");
|
|
82
|
+
ASSERT_EQ(w.size(), 1u);
|
|
83
|
+
EXPECT_NE(w[0].find("WARNING: variable bogus not specified as parameter"), std::string::npos);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
TEST(UnexpectedArgs, FunctionLiteralWarnsToo) {
|
|
87
|
+
auto w = warningsBothPaths("g = function(p) p * 2; echo(g(3, extra=9));");
|
|
88
|
+
ASSERT_EQ(w.size(), 1u);
|
|
89
|
+
EXPECT_NE(w[0].find("WARNING: variable extra not specified as parameter"), std::string::npos);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
TEST(UnexpectedArgs, TooManyPositionalArgsWarnsExactlyOnce) {
|
|
93
|
+
// One warning for the whole call, however many extra arguments -- the
|
|
94
|
+
// reference's own warned_for_extra_arguments latch.
|
|
95
|
+
auto w = warningsBothPaths("module m(a) { } m(1, 2, 3);");
|
|
96
|
+
ASSERT_EQ(w.size(), 1u);
|
|
97
|
+
EXPECT_NE(w[0].find("WARNING: Too many unnamed arguments supplied"), std::string::npos);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
TEST(UnexpectedArgs, DollarVariablesAreNeverUnexpected) {
|
|
101
|
+
// ContextFrame::is_config_variable: a $-name is a dynamic-scope
|
|
102
|
+
// override, not a parameter, so passing one to anything is fine.
|
|
103
|
+
EXPECT_TRUE(warningsBothPaths("module m(a=1) { } m(a=2, $custom=3, $fn=8);").empty());
|
|
104
|
+
EXPECT_TRUE(warningsBothPaths("function f(x=1) = x; echo(f(x=2, $custom=3));").empty());
|
|
105
|
+
EXPECT_TRUE(warningsBothPaths("sphere(r=1, $fn=8);").empty());
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
TEST(UnexpectedArgs, DeclaredParametersNeverWarn) {
|
|
109
|
+
EXPECT_TRUE(warningsBothPaths("module m(a, b=2) { } m(1, b=3);").empty());
|
|
110
|
+
EXPECT_TRUE(warningsBothPaths("cylinder(h=2, r1=1, r2=0, center=true);").empty());
|
|
111
|
+
EXPECT_TRUE(warningsBothPaths("linear_extrude(height=1, twist=10, convexity=2) square(1);").empty());
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
TEST(UnexpectedArgs, BuiltinPrimitiveWarns) {
|
|
115
|
+
auto w = warningsBothPaths("cube(size=2, bogus=9);");
|
|
116
|
+
ASSERT_EQ(w.size(), 1u);
|
|
117
|
+
EXPECT_NE(w[0].find("WARNING: variable bogus not specified as parameter"), std::string::npos);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// The transform/color/hull/CSG family never reaches evalModularCall once
|
|
121
|
+
// the bytecode compiler turns it into Op::PushBuiltinWrap/Op::PushCsgWrap
|
|
122
|
+
// -- the whole point of running these VM-on as well.
|
|
123
|
+
TEST(UnexpectedArgs, BuiltinsWithChildrenWarnOnBothPaths) {
|
|
124
|
+
EXPECT_TRUE(has(warningsBothPaths("translate([1,0,0], junk=1) cube(1);"), "variable junk"));
|
|
125
|
+
EXPECT_TRUE(has(warningsBothPaths("color(\"red\", junk=1) cube(1);"), "variable junk"));
|
|
126
|
+
EXPECT_TRUE(has(warningsBothPaths("hull(junk=1) cube(1);"), "variable junk"));
|
|
127
|
+
EXPECT_TRUE(has(warningsBothPaths("union(junk=1) cube(1);"), "variable junk"));
|
|
128
|
+
EXPECT_TRUE(has(warningsBothPaths("difference(junk=1) { cube(1); }"), "variable junk"));
|
|
129
|
+
EXPECT_TRUE(has(warningsBothPaths("offset(r=1, junk=1) square(1);"), "variable junk"));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// The `#`/`%`/`!` modifiers share BuiltinWrapSite with the transforms but
|
|
133
|
+
// carry no argument list at all -- must not trip the ModularCall cast.
|
|
134
|
+
TEST(UnexpectedArgs, ModifiersAreNotCalls) {
|
|
135
|
+
EXPECT_TRUE(warningsBothPaths("#translate([1,0,0]) cube(1);").empty());
|
|
136
|
+
EXPECT_TRUE(warningsBothPaths("%cube(1);").empty());
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Real OpenSCAD's builtin FUNCTIONS read their arguments positionally
|
|
140
|
+
// without Parameters::parse, so they warn about nothing -- verified against
|
|
141
|
+
// 2022.08.22, where both `sin(x=30)` and `sin(bogus=30)` return 0.5 in
|
|
142
|
+
// silence. textmetrics/fontmetrics are the exceptions that do parse.
|
|
143
|
+
TEST(UnexpectedArgs, BuiltinFunctionsDoNotWarn) {
|
|
144
|
+
EXPECT_TRUE(warningsBothPaths("echo(sin(bogus=30));").empty());
|
|
145
|
+
EXPECT_TRUE(warningsBothPaths("echo(len(bogus=[1,2]));").empty());
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
TEST(UnexpectedArgs, TextMetricsWarns) {
|
|
149
|
+
auto w = warningsBothPaths("echo(textmetrics(text=\"hi\", size=5, nope=1));");
|
|
150
|
+
EXPECT_TRUE(has(w, "variable nope not specified as parameter"));
|
|
151
|
+
}
|