openscad-cpp-evaluator 1.44.0__tar.gz → 1.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-1.44.0 → openscad_cpp_evaluator-1.45.0}/PKG-INFO +1 -1
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/bytecode.hpp +27 -18
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/evaluator.hpp +14 -7
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/pyproject.toml +1 -1
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/builtins/function_builtins.cpp +5 -3
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/bytecode_compiler.cpp +40 -20
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/bytecode_vm.cpp +16 -8
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/expr_eval.cpp +1 -3
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/stmt_eval.cpp +59 -21
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/user_calls.cpp +1 -3
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/value.cpp +43 -12
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_bytecode_compiler.cpp +81 -7
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_openscad_parity.cpp +5 -3
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_value.cpp +22 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/uv.lock +1 -1
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/.github/workflows/wheels.yml +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/.gitignore +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/.gitmodules +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/LICENSE +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/README.md +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/bindings/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/bindings/ast_to_py.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/bindings/module.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/cmake/embed_font.cmake +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/cmake/patch_manifold.cmake +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/examples/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/examples/eval_perf_benchmark.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/examples/manifold_cache_reuse.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/examples/minimal_debugger.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/.gitignore +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/LICENSE +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/README.md +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope_table.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/src/.DS_Store +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/src/api.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/src/comments.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/src/position.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/src/scope.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/tests/test_concurrent_parse.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/tests/test_profile_time.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/tests/test_render_expression.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/tests/test_strict_commas.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/bytecode_vm.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/colored_body.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/coverage.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/export.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/font_match.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/format_closure.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/freetype_font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/mesh_check.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/profile.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/scope_trail.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/segments.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/utf8.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/value.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/python/openscad_cpp_evaluator/__init__.py +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/resources/fonts/LICENSE +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/resources/fonts/LiberationSans-Bold.ttf +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/resources/fonts/LiberationSans-BoldItalic.ttf +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/resources/fonts/LiberationSans-Italic.ttf +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/resources/fonts/LiberationSans-Regular.ttf +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/builtins/booleans.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/builtins/builtins.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/builtins/call_args.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/builtins/color.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/builtins/control.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/builtins/dxf_dim.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/builtins/extrude.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/builtins/import.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/builtins/modifiers.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/builtins/primitives_2d.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/builtins/primitives_3d.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/builtins/profile_time.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/builtins/registry.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/builtins/roof.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/builtins/segments.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/builtins/surface.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/builtins/text.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/builtins/topology.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/builtins/transforms.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/colored_body.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/coverage.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/csg_generate.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/csg_resolve.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/css_colors.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/debug/debug_repl.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/debug_profile.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/eval_context.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/eval_error.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/eval_use.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/export.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/format_closure.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/import/dxf_import.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/import/mesh_import.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/import/scene_import.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/import/surface_load.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/import/svg_import.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/measure_geometry.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/text/font_match.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/text/freetype_font_provider.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/text/text_metrics.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/utf8.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/xkcd_colors.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/xkcd_colors.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_booleans.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_children_separate.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_cli.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_control_flow.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_coverage.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_csg_tree.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_debug_hooks.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_discretizer.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_dxf_svg_import.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_eval_context.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_export.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_extrude_roof.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_feature_detection.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_import_export.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_include_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_multi_color_merge.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_primitives.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_profile_time.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_profiling.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_python_bindings.py +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_render_expr.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_scope_trail.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_scoping.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_surface.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_tail_calls.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_text.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_transforms.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_undef_args.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_unexpected_args.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_use.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_viewport_params.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tools/cli/cli_lib.cpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tools/cli/cli_lib.hpp +0 -0
- {openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tools/cli/main.cpp +0 -0
|
@@ -505,7 +505,7 @@ enum class Op {
|
|
|
505
505
|
// anything compileStatementList doesn't give its own real bytecode.
|
|
506
506
|
// (Assignment/ModularEcho/ModularAssert/ModularLet used to fall here
|
|
507
507
|
// too; they now have their own real bytecode -- Op::StoreModuleVar/
|
|
508
|
-
// Op::Echo/Op::
|
|
508
|
+
// Op::Echo/Op::AssertPass+AssertFail/Op::OpenLetScope+StoreLetVar -- purely
|
|
509
509
|
// a throughput change, since none of these were ever the recursion-
|
|
510
510
|
// depth risk this compiler targets. `#`/`%`/`!` modifiers and
|
|
511
511
|
// translate/rotate/scale/mirror/multmatrix/resize/color used to fall
|
|
@@ -634,14 +634,9 @@ enum class Op {
|
|
|
634
634
|
// the position recorded into dynPositions).
|
|
635
635
|
StoreModuleVar,
|
|
636
636
|
|
|
637
|
-
// ModularEcho/ModularAssert's own statement form share Op::Echo
|
|
638
|
-
//
|
|
639
|
-
//
|
|
640
|
-
// (Op::Echo, above; Op::AssertStatement, below) for why the
|
|
641
|
-
// EXPRESSION-form opcodes are directly reusable (statement-shaped
|
|
642
|
-
// already: no value pushed, straight fall-through) while assert's
|
|
643
|
-
// needs its own op (named-argument support + eager-not-lazy message
|
|
644
|
-
// evaluation, both genuinely different from AssertOp's own contract).
|
|
637
|
+
// ModularEcho/ModularAssert's own statement form share Op::Echo and
|
|
638
|
+
// Op::AssertPass/AssertFail (below) with the expression forms: both are
|
|
639
|
+
// statement-shaped already (no value pushed, straight fall-through).
|
|
645
640
|
|
|
646
641
|
// Isolates ONE inline-compiled sub-expression's own `$`-writes from the
|
|
647
642
|
// rest of this chunk's shared, long-lived ctx -- pushes ctx.
|
|
@@ -697,12 +692,15 @@ enum class Op {
|
|
|
697
692
|
// the handler itself, kept for consistency/future debugging only).
|
|
698
693
|
StoreLetVar,
|
|
699
694
|
|
|
700
|
-
//
|
|
701
|
-
//
|
|
702
|
-
//
|
|
703
|
-
//
|
|
704
|
-
//
|
|
705
|
-
|
|
695
|
+
// assert(): the condition is compiled first, then JumpIfFalse to the
|
|
696
|
+
// failure path; the passing path never evaluates any other argument
|
|
697
|
+
// (see Evaluator::evalAssert). a = index into CompiledChunk::assertSites.
|
|
698
|
+
// AssertPass prints the site's unexpected-argument warnings and runs a
|
|
699
|
+
// statement's chained children; it is emitted only when the site has
|
|
700
|
+
// either. AssertFail pops every non-condition argument (source order)
|
|
701
|
+
// and throws via Evaluator::failAssert.
|
|
702
|
+
AssertPass,
|
|
703
|
+
AssertFail,
|
|
706
704
|
// a = nativeStatements index of the AST node whose arm this is. Emitted
|
|
707
705
|
// only when the Evaluator was built with coverage on (compile-time
|
|
708
706
|
// flag, and chunks are per-Evaluator): Evaluator::coverHit(node), nothing
|
|
@@ -711,6 +709,17 @@ enum class Op {
|
|
|
711
709
|
Cover,
|
|
712
710
|
};
|
|
713
711
|
|
|
712
|
+
// Which of an assert() call's arguments are its condition and message, and
|
|
713
|
+
// whether the call has any unexpected argument to warn about -- all fixed by
|
|
714
|
+
// the call's shape, so worked out once per call site (assertLayout,
|
|
715
|
+
// stmt_eval.cpp). -1 = not given.
|
|
716
|
+
struct AssertLayout {
|
|
717
|
+
int cond = -1;
|
|
718
|
+
int msg = -1;
|
|
719
|
+
bool warns = false;
|
|
720
|
+
};
|
|
721
|
+
AssertLayout assertLayout(const std::vector<std::unique_ptr<oscad::Argument>>& arguments);
|
|
722
|
+
|
|
714
723
|
struct Instruction {
|
|
715
724
|
Op op;
|
|
716
725
|
int a = 0;
|
|
@@ -1014,10 +1023,10 @@ struct CompiledChunk {
|
|
|
1014
1023
|
const oscad::ASTNode* node = nullptr;
|
|
1015
1024
|
};
|
|
1016
1025
|
|
|
1017
|
-
// One Op::
|
|
1018
|
-
// form, which has no children.
|
|
1026
|
+
// One Op::AssertPass/AssertFail site. `statement` is null for the
|
|
1027
|
+
// expression form, which has no children.
|
|
1019
1028
|
struct AssertSite {
|
|
1020
|
-
|
|
1029
|
+
AssertLayout layout;
|
|
1021
1030
|
const std::vector<std::unique_ptr<oscad::Argument>>* arguments = nullptr;
|
|
1022
1031
|
const oscad::ASTNode* node = nullptr;
|
|
1023
1032
|
const oscad::ModularAssert* statement = nullptr;
|
|
@@ -565,13 +565,20 @@ public:
|
|
|
565
565
|
void warnUndefinedEscapes(const oscad::StringLiteral& lit, int count);
|
|
566
566
|
// let() keeps the FIRST binding of a repeated name: OpenSCAD evaluates
|
|
567
567
|
// the later right-hand side, warns with its value, and discards it.
|
|
568
|
-
//
|
|
569
|
-
//
|
|
570
|
-
//
|
|
571
|
-
//
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
568
|
+
// assert(), interpreted: the condition first, and only on failure the
|
|
569
|
+
// message and any other argument -- see the definition (stmt_eval.cpp)
|
|
570
|
+
// for why this deliberately diverges from OpenSCAD. `maybeCompiled`
|
|
571
|
+
// picks evalExprMaybeCompiled (statement form) over evalExpr.
|
|
572
|
+
void evalAssert(const std::vector<std::unique_ptr<oscad::Argument>>& arguments, const oscad::ASTNode& node,
|
|
573
|
+
EvalContext& ctx, bool maybeCompiled);
|
|
574
|
+
// The unexpected-argument warnings, which a passing assert still prints.
|
|
575
|
+
void warnAssertArgs(const std::vector<std::unique_ptr<oscad::Argument>>& arguments, const AssertLayout& layout);
|
|
576
|
+
// A failed (or condition-less) assert, once every non-condition argument
|
|
577
|
+
// has been evaluated: warns about unexpected arguments, then throws via
|
|
578
|
+
// error(). `message` is null when none was given; it prints as echo()
|
|
579
|
+
// would print it.
|
|
580
|
+
[[noreturn]] void failAssert(const std::vector<std::unique_ptr<oscad::Argument>>& arguments,
|
|
581
|
+
const AssertLayout& layout, const Value* message, const oscad::ASTNode& node);
|
|
575
582
|
void warnDuplicateLet(const std::string& name, const Value& v, const oscad::Position* position);
|
|
576
583
|
template <typename Assignments>
|
|
577
584
|
static bool repeatsEarlierLetName(const Assignments& assignments, size_t i) {
|
{openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/src/builtins/function_builtins.cpp
RENAMED
|
@@ -1242,9 +1242,12 @@ Value evalBuiltinFunctionResolved(Evaluator& ev, BuiltinFnId id, const std::vect
|
|
|
1242
1242
|
// was 0, concat(a=[1], b=[2]) was [], rands(seed_value=) went unseeded.
|
|
1243
1243
|
// (textmetrics/fontmetrics -- with declaredParams -- and dxf_dim/
|
|
1244
1244
|
// dxf_cross bind by name in OpenSCAD too.)
|
|
1245
|
+
// The common all-positional call goes straight through, with no
|
|
1246
|
+
// reordered copy built (or destroyed) on its way.
|
|
1245
1247
|
const bool byName = declaredParams || id == BuiltinFnId::DxfDim || id == BuiltinFnId::DxfCross;
|
|
1248
|
+
if (byName || args.named.empty()) return evalBuiltinFunctionInOrder(ev, id, name, args, node);
|
|
1246
1249
|
CallArgs ordered;
|
|
1247
|
-
if (
|
|
1250
|
+
if (node.kind() == oscad::NodeKind::PrimaryCall) {
|
|
1248
1251
|
int k = 0, out = 0;
|
|
1249
1252
|
for (const auto& a : static_cast<const oscad::PrimaryCall&>(node).arguments) {
|
|
1250
1253
|
const Value* v = nullptr;
|
|
@@ -1258,8 +1261,7 @@ Value evalBuiltinFunctionResolved(Evaluator& ev, BuiltinFnId id, const std::vect
|
|
|
1258
1261
|
ordered.setPositional(out++, v ? *v : Value{});
|
|
1259
1262
|
}
|
|
1260
1263
|
}
|
|
1261
|
-
|
|
1262
|
-
return evalBuiltinFunctionInOrder(ev, id, name, argsInOrder, node);
|
|
1264
|
+
return evalBuiltinFunctionInOrder(ev, id, name, ordered, node);
|
|
1263
1265
|
}
|
|
1264
1266
|
|
|
1265
1267
|
Value evalBuiltinFunctionInOrder(Evaluator& ev, BuiltinFnId id, const std::string& name, const CallArgs& args,
|
|
@@ -913,17 +913,10 @@ public:
|
|
|
913
913
|
}
|
|
914
914
|
|
|
915
915
|
case NodeKind::AssertOp: {
|
|
916
|
-
//
|
|
917
|
-
// does -- see Evaluator::checkAssert.
|
|
916
|
+
// Only the condition unless it fails -- see Evaluator::evalAssert.
|
|
918
917
|
auto& n = static_cast<const oscad::AssertOp&>(node);
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
site.arguments = &n.arguments;
|
|
922
|
-
site.argCount = static_cast<int>(n.arguments.size());
|
|
923
|
-
for (const auto& arg : n.arguments) compileExpr(*argExpr(*arg), out, scope); // never tail
|
|
924
|
-
int siteIdx = static_cast<int>(chunk_.assertSites.size());
|
|
925
|
-
chunk_.assertSites.push_back(std::move(site));
|
|
926
|
-
out.push_back({Op::AssertStatement, siteIdx, 0, &n.position()});
|
|
918
|
+
compileAssert(n.arguments, n, nullptr, out,
|
|
919
|
+
[&](const oscad::Expression& e) { compileExpr(e, out, scope); }); // never tail
|
|
927
920
|
compileExpr(*n.body, out, scope, tail);
|
|
928
921
|
return;
|
|
929
922
|
}
|
|
@@ -1313,6 +1306,40 @@ public:
|
|
|
1313
1306
|
out.push_back({Op::CloseExprScope, 0, 0, nullptr});
|
|
1314
1307
|
}
|
|
1315
1308
|
|
|
1309
|
+
// assert(), either form, mirroring Evaluator::evalAssert:
|
|
1310
|
+
// <condition> JumpIfFalse fail [AssertPass] Jump end
|
|
1311
|
+
// fail: <every other argument, source order> AssertFail
|
|
1312
|
+
// end:
|
|
1313
|
+
// AssertPass only when there is something for it to do; with no
|
|
1314
|
+
// condition at all, straight to the failure path.
|
|
1315
|
+
template <typename CompileArg>
|
|
1316
|
+
void compileAssert(const std::vector<std::unique_ptr<oscad::Argument>>& arguments, const oscad::ASTNode& node,
|
|
1317
|
+
const oscad::ModularAssert* statement, std::vector<Instruction>& out, CompileArg compileArg) {
|
|
1318
|
+
CompiledChunk::AssertSite site;
|
|
1319
|
+
site.layout = assertLayout(arguments);
|
|
1320
|
+
site.node = &node;
|
|
1321
|
+
site.statement = statement;
|
|
1322
|
+
site.arguments = &arguments;
|
|
1323
|
+
const int siteIdx = static_cast<int>(chunk_.assertSites.size());
|
|
1324
|
+
chunk_.assertSites.push_back(site);
|
|
1325
|
+
const int cond = site.layout.cond;
|
|
1326
|
+
std::optional<size_t> jumpEnd;
|
|
1327
|
+
if (cond >= 0) {
|
|
1328
|
+
compileArg(*argExpr(*arguments[static_cast<size_t>(cond)]));
|
|
1329
|
+
const size_t jumpFail = out.size();
|
|
1330
|
+
out.push_back({Op::JumpIfFalse, 0, 0, nullptr});
|
|
1331
|
+
if (site.layout.warns || (statement && !statement->children.empty()))
|
|
1332
|
+
out.push_back({Op::AssertPass, siteIdx, 0, &node.position()});
|
|
1333
|
+
jumpEnd = out.size();
|
|
1334
|
+
out.push_back({Op::Jump, 0, 0, nullptr});
|
|
1335
|
+
out[jumpFail].a = static_cast<int>(out.size());
|
|
1336
|
+
}
|
|
1337
|
+
for (size_t i = 0; i < arguments.size(); ++i)
|
|
1338
|
+
if (static_cast<int>(i) != cond) compileArg(*argExpr(*arguments[i]));
|
|
1339
|
+
out.push_back({Op::AssertFail, siteIdx, 0, &node.position()});
|
|
1340
|
+
if (jumpEnd) out[*jumpEnd].a = static_cast<int>(out.size());
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1316
1343
|
// Shared by ModularCall's Transform/Color-kind branch and the 3 real
|
|
1317
1344
|
// modifier cases (ModularModifierHighlight/Background/ShowOnly),
|
|
1318
1345
|
// below -- emits one Op::PushBuiltinWrap/PopBuiltinWrap bracket around
|
|
@@ -1544,7 +1571,7 @@ public:
|
|
|
1544
1571
|
return;
|
|
1545
1572
|
// Assignment/ModularEcho/ModularAssert: real bytecode instead
|
|
1546
1573
|
// of Op::NativeStatement -- a throughput improvement (see
|
|
1547
|
-
// CheckDebugStatement/StoreModuleVar/
|
|
1574
|
+
// CheckDebugStatement/StoreModuleVar/AssertPass+AssertFail's own doc
|
|
1548
1575
|
// comments, bytecode.hpp), NOT a recursion-safety one (these
|
|
1549
1576
|
// were never the risk Stage 2 targeted -- see NativeStatement's
|
|
1550
1577
|
// own doc comment). Assignment specifically closes a real
|
|
@@ -1602,16 +1629,9 @@ public:
|
|
|
1602
1629
|
// Like AssertOp's compiled form, plus chained children.
|
|
1603
1630
|
auto& n = static_cast<const oscad::ModularAssert&>(stmt);
|
|
1604
1631
|
out.push_back({Op::CheckDebugStatement, internNativeStatement(&stmt), 0, nullptr});
|
|
1605
|
-
CompiledChunk::AssertSite site;
|
|
1606
|
-
site.node = &n;
|
|
1607
|
-
site.statement = &n;
|
|
1608
|
-
site.arguments = &n.arguments;
|
|
1609
|
-
site.argCount = static_cast<int>(n.arguments.size());
|
|
1610
1632
|
CompileScope exprScope;
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
chunk_.assertSites.push_back(std::move(site));
|
|
1614
|
-
out.push_back({Op::AssertStatement, siteIdx, 0, &n.position()});
|
|
1633
|
+
compileAssert(n.arguments, n, &n, out,
|
|
1634
|
+
[&](const oscad::Expression& e) { compileIsolatedExpr(e, out, exprScope); });
|
|
1615
1635
|
return;
|
|
1616
1636
|
}
|
|
1617
1637
|
case NodeKind::ModularLet: {
|
|
@@ -1105,7 +1105,7 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
1105
1105
|
ev.emitEcho(pairs);
|
|
1106
1106
|
// The STATEMENT form can carry children and the
|
|
1107
1107
|
// reference renders them; same tail as
|
|
1108
|
-
// Op::
|
|
1108
|
+
// Op::AssertPass below. Null node = the expression
|
|
1109
1109
|
// form (`echo(...) 1+1`), which has none.
|
|
1110
1110
|
if (site.node && !site.node->children.empty())
|
|
1111
1111
|
ev.evalChildren(site.node->children, ctx);
|
|
@@ -1567,14 +1567,9 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
1567
1567
|
++f.pc;
|
|
1568
1568
|
break;
|
|
1569
1569
|
}
|
|
1570
|
-
case Op::
|
|
1570
|
+
case Op::AssertPass: {
|
|
1571
1571
|
const CompiledChunk::AssertSite& site = f.chunk->assertSites[static_cast<size_t>(ins.a)];
|
|
1572
|
-
|
|
1573
|
-
for (int i = site.argCount - 1; i >= 0; --i) {
|
|
1574
|
-
args[static_cast<size_t>(i)] = std::move(f.stack.back());
|
|
1575
|
-
f.stack.pop_back();
|
|
1576
|
-
}
|
|
1577
|
-
ev.checkAssert(*site.arguments, args, *site.node);
|
|
1572
|
+
ev.warnAssertArgs(*site.arguments, site.layout);
|
|
1578
1573
|
// Rare (assert(...) translate(...) children();-shaped) --
|
|
1579
1574
|
// not worth its own compiled path; evalChildren already
|
|
1580
1575
|
// tries ITS OWN compiled fast path internally regardless.
|
|
@@ -1583,6 +1578,19 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
1583
1578
|
++f.pc;
|
|
1584
1579
|
break;
|
|
1585
1580
|
}
|
|
1581
|
+
case Op::AssertFail: {
|
|
1582
|
+
// Every argument but the condition is on the stack, in
|
|
1583
|
+
// source order; only the message's value is wanted.
|
|
1584
|
+
const CompiledChunk::AssertSite& site = f.chunk->assertSites[static_cast<size_t>(ins.a)];
|
|
1585
|
+
const AssertLayout& layout = site.layout;
|
|
1586
|
+
Value message;
|
|
1587
|
+
for (int i = static_cast<int>(site.arguments->size()) - 1; i >= 0; --i) {
|
|
1588
|
+
if (i == layout.cond) continue;
|
|
1589
|
+
if (i == layout.msg) message = std::move(f.stack.back());
|
|
1590
|
+
f.stack.pop_back();
|
|
1591
|
+
}
|
|
1592
|
+
ev.failAssert(*site.arguments, layout, layout.msg >= 0 ? &message : nullptr, *site.node);
|
|
1593
|
+
}
|
|
1586
1594
|
case Op::NativeCondJumpIfFalse: {
|
|
1587
1595
|
const oscad::Expression* cond = f.chunk->nativeExprs[static_cast<size_t>(ins.a)];
|
|
1588
1596
|
const bool truthyVal = truthy(ev.evalExprMaybeCompiled(*cond, ctx));
|
|
@@ -492,9 +492,7 @@ Value Evaluator::evalProfileTimeExpr(const oscad::ProfileTimeOp& node, EvalConte
|
|
|
492
492
|
|
|
493
493
|
Value Evaluator::evalAssertExpr(const oscad::AssertOp& node, EvalContext& ctx) {
|
|
494
494
|
checkDebug(node, ctx); // _expr_assert, before the condition is evaluated
|
|
495
|
-
|
|
496
|
-
for (const auto& arg : node.arguments) values.push_back(evalExpr(*argExpr(*arg), ctx));
|
|
497
|
-
checkAssert(node.arguments, values, node);
|
|
495
|
+
evalAssert(node.arguments, node, ctx, /*maybeCompiled=*/false);
|
|
498
496
|
return evalExpr(*node.body, ctx);
|
|
499
497
|
}
|
|
500
498
|
|
|
@@ -74,41 +74,79 @@ void Evaluator::doEcho(const std::vector<std::unique_ptr<oscad::Argument>>& argu
|
|
|
74
74
|
emitEcho(pairs);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
namespace {
|
|
78
|
+
const std::vector<std::string> kAssertParams{"condition", "message"};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
AssertLayout assertLayout(const std::vector<std::unique_ptr<oscad::Argument>>& arguments) {
|
|
81
82
|
// A named argument wins; positional 0/1 fill whichever is left.
|
|
82
|
-
|
|
83
|
+
AssertLayout layout;
|
|
83
84
|
for (size_t i = 0; i < arguments.size(); ++i) {
|
|
84
85
|
if (arguments[i]->kind() != oscad::NodeKind::NamedArgument) continue;
|
|
85
86
|
const std::string& name = static_cast<const oscad::NamedArgument&>(*arguments[i]).name->name;
|
|
86
|
-
if (name == "condition" &&
|
|
87
|
-
else if (name == "message" &&
|
|
87
|
+
if (name == "condition" && layout.cond < 0) layout.cond = static_cast<int>(i);
|
|
88
|
+
else if (name == "message" && layout.msg < 0) layout.msg = static_cast<int>(i);
|
|
89
|
+
else if (name != "condition" && name != "message" && !isConfigVariable(name)) layout.warns = true;
|
|
88
90
|
}
|
|
89
|
-
|
|
91
|
+
int positional = 0;
|
|
90
92
|
for (size_t i = 0; i < arguments.size(); ++i) {
|
|
91
93
|
if (arguments[i]->kind() == oscad::NodeKind::NamedArgument) continue;
|
|
92
|
-
if (positional == 0 &&
|
|
93
|
-
else if (positional == 1 &&
|
|
94
|
-
++positional;
|
|
94
|
+
if (positional == 0 && layout.cond < 0) layout.cond = static_cast<int>(i);
|
|
95
|
+
else if (positional == 1 && layout.msg < 0) layout.msg = static_cast<int>(i);
|
|
96
|
+
if (++positional > static_cast<int>(kAssertParams.size())) layout.warns = true;
|
|
95
97
|
}
|
|
96
|
-
|
|
98
|
+
return layout;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
void Evaluator::warnAssertArgs(const std::vector<std::unique_ptr<oscad::Argument>>& arguments,
|
|
102
|
+
const AssertLayout& layout) {
|
|
103
|
+
if (layout.warns) warnUnexpectedArgs(*this, kAssertParams, arguments);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
void Evaluator::failAssert(const std::vector<std::unique_ptr<oscad::Argument>>& arguments,
|
|
107
|
+
const AssertLayout& layout, const Value* message, const oscad::ASTNode& node) {
|
|
108
|
+
warnAssertArgs(arguments, layout);
|
|
97
109
|
std::string err = "Assertion";
|
|
98
|
-
if (cond) err += " '" + formatExpression(*argExpr(*arguments[
|
|
110
|
+
if (layout.cond >= 0) err += " '" + formatExpression(*argExpr(*arguments[static_cast<size_t>(layout.cond)])) + "'";
|
|
99
111
|
err += " failed";
|
|
100
|
-
if (
|
|
112
|
+
if (message) err += ": " + fmtValue(*message);
|
|
101
113
|
error(err, node, "assert");
|
|
102
114
|
}
|
|
103
115
|
|
|
116
|
+
// DELIBERATE DIVERGENCE FROM OPENSCAD: a passing assert() evaluates its
|
|
117
|
+
// condition and nothing else, the way `||` skips its right operand.
|
|
118
|
+
// OpenSCAD's Assert::performAssert evaluates every argument first, so there
|
|
119
|
+
// a passing `assert(true, echo("e") "m")` echoes, `assert(true, nosuch)`
|
|
120
|
+
// warns, and a message calling a user function runs it; here none of them
|
|
121
|
+
// does. BOSL2 validates nearly every call with `assert(cond, str(...))`,
|
|
122
|
+
// and building those never-shown messages was ~4% of its evaluation time.
|
|
123
|
+
// A failing (or condition-less) assert evaluates every other argument, in
|
|
124
|
+
// source order, after the condition, so its output is unchanged; the
|
|
125
|
+
// unexpected-argument warnings depend only on the call's shape and still
|
|
126
|
+
// print on every call. The compiled form (Op::AssertPass/AssertFail) does
|
|
127
|
+
// the same.
|
|
128
|
+
void Evaluator::evalAssert(const std::vector<std::unique_ptr<oscad::Argument>>& arguments, const oscad::ASTNode& node,
|
|
129
|
+
EvalContext& ctx, bool maybeCompiled) {
|
|
130
|
+
const AssertLayout layout = assertLayout(arguments);
|
|
131
|
+
auto eval = [&](size_t i) {
|
|
132
|
+
const oscad::Expression& e = *argExpr(*arguments[i]);
|
|
133
|
+
return maybeCompiled ? evalExprMaybeCompiled(e, ctx) : evalExpr(e, ctx);
|
|
134
|
+
};
|
|
135
|
+
if (layout.cond >= 0 && truthy(eval(static_cast<size_t>(layout.cond)))) {
|
|
136
|
+
warnAssertArgs(arguments, layout);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
Value message;
|
|
140
|
+
for (size_t i = 0; i < arguments.size(); ++i) {
|
|
141
|
+
if (static_cast<int>(i) == layout.cond) continue;
|
|
142
|
+
Value v = eval(i);
|
|
143
|
+
if (static_cast<int>(i) == layout.msg) message = std::move(v);
|
|
144
|
+
}
|
|
145
|
+
failAssert(arguments, layout, layout.msg >= 0 ? &message : nullptr, node);
|
|
146
|
+
}
|
|
147
|
+
|
|
104
148
|
void Evaluator::evalAssertStatement(const oscad::ModularAssert& node, EvalContext& ctx) {
|
|
105
|
-
|
|
106
|
-
// message=...)), unlike the expression form's raw positional indexing
|
|
107
|
-
// -- see evalAssertExpr. Mirrors _eval_statement_impl's ModularAssert
|
|
108
|
-
// branch exactly.
|
|
109
|
-
std::vector<Value> values;
|
|
110
|
-
for (const auto& arg : node.arguments) values.push_back(evalExprMaybeCompiled(*argExpr(*arg), ctx));
|
|
111
|
-
checkAssert(node.arguments, values, node);
|
|
149
|
+
evalAssert(node.arguments, node, ctx, /*maybeCompiled=*/true);
|
|
112
150
|
// Assertion passed -- propagate any chained child geometry (e.g.
|
|
113
151
|
// `assert(...) translate(...) children();`).
|
|
114
152
|
if (!node.children.empty()) evalChildren(node.children, ctx);
|
|
@@ -532,9 +532,7 @@ std::variant<Value, Evaluator::TailStep, Evaluator::NotTailStep> Evaluator::simp
|
|
|
532
532
|
// Mirrors evalAssertExpr.
|
|
533
533
|
auto& n = static_cast<const oscad::AssertOp&>(node);
|
|
534
534
|
checkDebug(n, ctx);
|
|
535
|
-
|
|
536
|
-
for (const auto& arg : n.arguments) values.push_back(evalExpr(*argExpr(*arg), ctx));
|
|
537
|
-
checkAssert(n.arguments, values, n);
|
|
535
|
+
evalAssert(n.arguments, n, ctx, /*maybeCompiled=*/false);
|
|
538
536
|
TailStep step;
|
|
539
537
|
step.nextExpr = n.body.get();
|
|
540
538
|
step.ctx = ctx;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
#include "openscad_cpp_evaluator/utf8.hpp"
|
|
5
5
|
|
|
6
6
|
#include <algorithm>
|
|
7
|
+
#include <charconv>
|
|
7
8
|
#include <cmath>
|
|
8
9
|
#include <cstdio>
|
|
9
10
|
#include <cstdlib>
|
|
@@ -486,29 +487,59 @@ std::string unescapeStringLiteral(const std::string& raw, int* undefinedEscapes)
|
|
|
486
487
|
}
|
|
487
488
|
|
|
488
489
|
namespace {
|
|
489
|
-
// The first
|
|
490
|
-
//
|
|
491
|
-
//
|
|
492
|
-
// decides every case but one: when it
|
|
493
|
-
// sixth digit, the true value may sit
|
|
494
|
-
// exact expansion settles it.
|
|
495
|
-
|
|
490
|
+
// The first 7 significant digits of |v| (all[0..6]) and the power of ten of
|
|
491
|
+
// the first one, plus whether the first 6 round UP: correctly rounded with
|
|
492
|
+
// exact ties rounding up (double-conversion's ToPrecision, which OpenSCAD
|
|
493
|
+
// prints with). A 17-digit rendering decides every case but one: when it
|
|
494
|
+
// reads exactly ...5000000000 past the sixth digit, the true value may sit
|
|
495
|
+
// just either side of the tie, so the exact expansion settles it.
|
|
496
|
+
bool exactSevenDigits(double av, char all[17], int& exp10) {
|
|
496
497
|
char buf[32];
|
|
497
498
|
std::snprintf(buf, sizeof buf, "%.16e", av); // d.dddddddddddddddde[+-]x
|
|
498
499
|
exp10 = std::atoi(std::strchr(buf, 'e') + 1);
|
|
499
|
-
char all[17];
|
|
500
500
|
all[0] = buf[0];
|
|
501
501
|
std::memcpy(all + 1, buf + 2, 16);
|
|
502
|
-
bool up;
|
|
503
502
|
if (all[6] == '5' && std::memcmp(all + 7, "0000000000", 10) == 0) {
|
|
504
503
|
static thread_local char exact[1100];
|
|
505
504
|
std::snprintf(exact, sizeof exact, "%.1000e", av); // the exact expansion
|
|
506
505
|
// exact[7] is the 7th significant digit ("d.dddddd..."); 5 or more
|
|
507
506
|
// rounds up, an exact tie included.
|
|
508
|
-
|
|
509
|
-
} else {
|
|
510
|
-
up = all[6] >= '5';
|
|
507
|
+
return exact[7] >= '5';
|
|
511
508
|
}
|
|
509
|
+
return all[6] >= '5';
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
// The same answer from the SHORTEST round-trip rendering D (std::to_chars,
|
|
513
|
+
// several times cheaper than printf), which is safe for a normal double:
|
|
514
|
+
// its rounding interval is ~1e-16 relative, far narrower than the 1e-6
|
|
515
|
+
// spacing of 7-digit decimals, so at most one 7-digit decimal lies in it.
|
|
516
|
+
// If the rounding boundary B (a 7-digit ...5) is in the interval, D is B
|
|
517
|
+
// itself; otherwise D and |v| lie on the same side of B and round alike.
|
|
518
|
+
// So D decides every case except D == B exactly, where |v| may be just
|
|
519
|
+
// either side of the tie -- returns false then, for exactSevenDigits. A
|
|
520
|
+
// subnormal's interval is far wider (5e-324 renders shortest as "5e-324"
|
|
521
|
+
// but prints as 4.94066e-324), so subnormals never come here.
|
|
522
|
+
bool shortestSevenDigits(double av, char all[17], int& exp10, bool& up) {
|
|
523
|
+
char buf[32];
|
|
524
|
+
const std::to_chars_result res = std::to_chars(buf, buf + sizeof buf, av, std::chars_format::scientific);
|
|
525
|
+
int n = 0;
|
|
526
|
+
const char* p = buf;
|
|
527
|
+
for (; *p != 'e'; ++p)
|
|
528
|
+
if (*p != '.') all[n++] = *p;
|
|
529
|
+
if (n == 7 && all[6] == '5') return false;
|
|
530
|
+
for (; n < 7; ++n) all[n] = '0';
|
|
531
|
+
std::from_chars(p + (p[1] == '+' ? 2 : 1), res.ptr, exp10);
|
|
532
|
+
up = all[6] >= '5';
|
|
533
|
+
return true;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// The first 6 significant digits of |v|, rounded as above, and the power
|
|
537
|
+
// of ten of the first one.
|
|
538
|
+
void sixDigits(double av, char digits[6], int& exp10) {
|
|
539
|
+
char all[17];
|
|
540
|
+
bool up;
|
|
541
|
+
if (av < std::numeric_limits<double>::min() || !shortestSevenDigits(av, all, exp10, up))
|
|
542
|
+
up = exactSevenDigits(av, all, exp10);
|
|
512
543
|
std::memcpy(digits, all, 6);
|
|
513
544
|
if (up) {
|
|
514
545
|
int k = 5;
|
{openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_bytecode_compiler.cpp
RENAMED
|
@@ -1867,17 +1867,91 @@ TEST(ModuleBodyCompiles, EchoStatementCompilesWithNamedAndPositionalArgs) {
|
|
|
1867
1867
|
EXPECT_EQ(runCapturingEcho("echo(1, b=2, 3);"), "ECHO: 1, b = 2, 3");
|
|
1868
1868
|
}
|
|
1869
1869
|
|
|
1870
|
-
TEST(ModuleBodyCompiles,
|
|
1870
|
+
TEST(ModuleBodyCompiles, AssertStatementCompilesWithNamedArgsInReverseOrder) {
|
|
1871
1871
|
ScopedVm vm(true);
|
|
1872
1872
|
// Named args in reverse order (message before condition), PLUS a 3rd,
|
|
1873
|
-
// logically-unused positional argument
|
|
1874
|
-
//
|
|
1875
|
-
//
|
|
1873
|
+
// logically-unused positional argument: the condition is found, the
|
|
1874
|
+
// pass skips every other argument (see Evaluator::evalAssert), and the
|
|
1875
|
+
// extra positional argument still warns.
|
|
1876
1876
|
std::string captured =
|
|
1877
|
-
runCapturingEcho("assert(message=\"unused, condition true\", condition=true, echo(\"side effect\"));\n"
|
|
1877
|
+
runCapturingEcho("assert(message=\"unused, condition true\", condition=true, echo(\"side effect\") 1);\n"
|
|
1878
1878
|
"echo(\"reached\");\n");
|
|
1879
|
-
|
|
1880
|
-
EXPECT_NE(captured.find("ECHO: \"reached\""), std::string::npos);
|
|
1879
|
+
EXPECT_EQ(captured.find("ECHO: \"side effect\""), std::string::npos) << captured;
|
|
1880
|
+
EXPECT_NE(captured.find("ECHO: \"reached\""), std::string::npos) << captured;
|
|
1881
|
+
}
|
|
1882
|
+
|
|
1883
|
+
// A passing assert() evaluates only its condition -- a deliberate
|
|
1884
|
+
// divergence from OpenSCAD, which evaluates the message too (see
|
|
1885
|
+
// Evaluator::evalAssert). Each script runs interpreted and compiled, in
|
|
1886
|
+
// both the statement and the expression form.
|
|
1887
|
+
namespace {
|
|
1888
|
+
struct AssertRun {
|
|
1889
|
+
std::string log;
|
|
1890
|
+
std::string error;
|
|
1891
|
+
};
|
|
1892
|
+
AssertRun runAssert(const std::string& code, bool vm) {
|
|
1893
|
+
ScopedVm scoped(vm);
|
|
1894
|
+
AssertRun r;
|
|
1895
|
+
Evaluator ev([&](const std::string& msg) { r.log += (r.log.empty() ? "" : "\n") + msg; });
|
|
1896
|
+
auto ast = parseSrc(code);
|
|
1897
|
+
auto scope = oscad::buildScopes(ast);
|
|
1898
|
+
EvalContext ctx = EvalContext::makeRoot(scope.get());
|
|
1899
|
+
try {
|
|
1900
|
+
ev.resolveTree(ast, ctx);
|
|
1901
|
+
} catch (const EvalError& e) {
|
|
1902
|
+
r.error = e.what();
|
|
1903
|
+
}
|
|
1904
|
+
return r;
|
|
1905
|
+
}
|
|
1906
|
+
const char* const kAssertPrelude = "function noisy() = echo(\"called\") \"m\";\n";
|
|
1907
|
+
} // namespace
|
|
1908
|
+
|
|
1909
|
+
TEST(AssertShortCircuit, PassingAssertSkipsTheMessage) {
|
|
1910
|
+
for (bool vm : {false, true}) {
|
|
1911
|
+
for (const std::string msg : {"echo(\"e\") \"m\"", "nosuch", "noisy()", "undef + 1"}) {
|
|
1912
|
+
for (const std::string code : {"assert(true, " + msg + ");",
|
|
1913
|
+
"function f(x) = assert(x, " + msg + ") 1; y = f(true);",
|
|
1914
|
+
"x = assert(true, " + msg + ") 2;"}) {
|
|
1915
|
+
const AssertRun r = runAssert(kAssertPrelude + code, vm);
|
|
1916
|
+
EXPECT_EQ(r.log, "") << "vm=" << vm << ": " << code;
|
|
1917
|
+
EXPECT_EQ(r.error, "") << "vm=" << vm << ": " << code;
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1921
|
+
}
|
|
1922
|
+
|
|
1923
|
+
TEST(AssertShortCircuit, FailingAssertStillEvaluatesTheMessage) {
|
|
1924
|
+
for (bool vm : {false, true}) {
|
|
1925
|
+
for (const std::string code : {"assert(false, noisy());", "function f(x) = assert(x, noisy()) 1; y = f(false);",
|
|
1926
|
+
"x = assert(false, noisy()) 2;"}) {
|
|
1927
|
+
const AssertRun r = runAssert(kAssertPrelude + code, vm);
|
|
1928
|
+
EXPECT_EQ(r.log, "ECHO: \"called\"") << "vm=" << vm << ": " << code;
|
|
1929
|
+
EXPECT_NE(r.error.find("failed: \"m\""), std::string::npos) << "vm=" << vm << ": " << r.error;
|
|
1930
|
+
}
|
|
1931
|
+
const AssertRun w = runAssert("assert(0, nosuch);", vm);
|
|
1932
|
+
EXPECT_NE(w.log.find("Ignoring unknown variable \"nosuch\""), std::string::npos) << "vm=" << vm << ": " << w.log;
|
|
1933
|
+
EXPECT_NE(w.error.find("Assertion '0' failed: undef"), std::string::npos) << "vm=" << vm << ": " << w.error;
|
|
1934
|
+
// Message given before the condition: the condition is still
|
|
1935
|
+
// evaluated first.
|
|
1936
|
+
const AssertRun o = runAssert("assert(message=echo(\"msg\") \"m\", condition=echo(\"cond\") false);", vm);
|
|
1937
|
+
EXPECT_EQ(o.log, "ECHO: \"cond\"\nECHO: \"msg\"") << "vm=" << vm;
|
|
1938
|
+
EXPECT_NE(o.error.find("failed: \"m\""), std::string::npos) << "vm=" << vm << ": " << o.error;
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1941
|
+
|
|
1942
|
+
TEST(AssertShortCircuit, PassingAssertStillWarnsAboutUnexpectedArguments) {
|
|
1943
|
+
for (bool vm : {false, true}) {
|
|
1944
|
+
for (const std::string code : {"assert(true, \"m\", 3);", "function f(x) = assert(x, \"m\", 3) 1; y = f(true);",
|
|
1945
|
+
"assert(true, bogus=1);", "x = assert(true, bogus=1) 2;"}) {
|
|
1946
|
+
const AssertRun r = runAssert(code, vm);
|
|
1947
|
+
EXPECT_TRUE(r.log.find("Too many unnamed arguments supplied") != std::string::npos ||
|
|
1948
|
+
r.log.find("variable bogus not specified as parameter") != std::string::npos)
|
|
1949
|
+
<< "vm=" << vm << ": " << code << " -> " << r.log;
|
|
1950
|
+
EXPECT_EQ(r.error, "") << "vm=" << vm << ": " << code;
|
|
1951
|
+
}
|
|
1952
|
+
// `assert(...) children` still runs the children once passed.
|
|
1953
|
+
EXPECT_EQ(runAssert("assert(true, nosuch) echo(\"child\");", vm).log, "ECHO: \"child\"") << "vm=" << vm;
|
|
1954
|
+
}
|
|
1881
1955
|
}
|
|
1882
1956
|
|
|
1883
1957
|
TEST(ModuleBodyCompiles, AssertStatementCompiledFormFailsWithNamedMessage) {
|
{openscad_cpp_evaluator-1.44.0 → openscad_cpp_evaluator-1.45.0}/tests/test_openscad_parity.cpp
RENAMED
|
@@ -446,8 +446,10 @@ std::string assertError(const std::string& src) {
|
|
|
446
446
|
}
|
|
447
447
|
} // namespace
|
|
448
448
|
|
|
449
|
-
// assert() passed; a message was always quoted; an undef message vanished
|
|
450
|
-
//
|
|
449
|
+
// assert() passed; a message was always quoted; an undef message vanished.
|
|
450
|
+
// The message is only evaluated on failure -- which OpenSCAD does NOT do: it
|
|
451
|
+
// evaluates every argument, pass or fail. That divergence is deliberate (see
|
|
452
|
+
// Evaluator::evalAssert).
|
|
451
453
|
TEST(Parity, AssertFollowsUpstream) {
|
|
452
454
|
EXPECT_NE(assertError("assert();").find("Assertion failed"), std::string::npos);
|
|
453
455
|
EXPECT_NE(assertError("function f() = assert() 1; x = f();").find("Assertion failed"), std::string::npos);
|
|
@@ -455,7 +457,7 @@ TEST(Parity, AssertFollowsUpstream) {
|
|
|
455
457
|
EXPECT_NE(assertError("x = assert(false, \"m\") 1;").find("Assertion 'false' failed: \"m\""), std::string::npos);
|
|
456
458
|
EXPECT_NE(assertError("assert(undef, undef);").find("failed: undef"), std::string::npos);
|
|
457
459
|
EXPECT_NE(assertError("assert(message=\"m\");").find("Assertion failed: \"m\""), std::string::npos);
|
|
458
|
-
|
|
460
|
+
EXPECT_FALSE(logged(run("x = assert(true, echo(\"lazy\") 1) 2;"), "ECHO: \"lazy\""));
|
|
459
461
|
EXPECT_TRUE(logged(run("assert(1, 2, 3);"), "Too many unnamed arguments supplied"));
|
|
460
462
|
}
|
|
461
463
|
|