openscad-cpp-evaluator 1.5.0__tar.gz → 1.6.1__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.5.0 → openscad_cpp_evaluator-1.6.1}/PKG-INFO +1 -1
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/bytecode_vm.hpp +24 -1
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/call_args.hpp +10 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/evaluator.hpp +20 -1
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/scope_trail.hpp +125 -45
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/pyproject.toml +1 -1
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/builtins/call_args.cpp +12 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/builtins/function_builtins.cpp +13 -12
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/bytecode_vm.cpp +46 -43
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/eval_context.cpp +17 -3
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/user_calls.cpp +11 -5
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_bytecode_compiler.cpp +35 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_scope_trail.cpp +24 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/.github/workflows/wheels.yml +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/.gitignore +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/.gitmodules +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/LICENSE +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/README.md +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/bindings/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/bindings/ast_to_py.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/bindings/module.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/cmake/embed_font.cmake +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/examples/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/examples/eval_perf_benchmark.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/examples/manifold_cache_reuse.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/examples/minimal_debugger.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/.gitignore +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/README.md +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope_table.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/src/api.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/src/comments.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/src/position.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/src/scope.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/tests/test_render_expression.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/bytecode.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/colored_body.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/export.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/font_match.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/format_closure.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/freetype_font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/mesh_check.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/profile.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/segments.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/utf8.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/value.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/python/openscad_cpp_evaluator/__init__.py +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/resources/fonts/LICENSE +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/resources/fonts/LiberationSans-Regular.ttf +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/builtins/booleans.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/builtins/builtins.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/builtins/color.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/builtins/control.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/builtins/dxf_dim.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/builtins/extrude.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/builtins/import.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/builtins/modifiers.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/builtins/primitives_2d.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/builtins/primitives_3d.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/builtins/registry.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/builtins/roof.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/builtins/segments.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/builtins/surface.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/builtins/text.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/builtins/topology.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/builtins/transforms.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/colored_body.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/csg_generate.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/csg_resolve.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/css_colors.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/debug/debug_repl.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/debug_profile.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/eval_error.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/eval_use.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/export.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/format_closure.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/import/dxf_import.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/import/mesh_import.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/import/surface_load.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/import/svg_import.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/measure_geometry.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/stmt_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/text/font_match.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/text/freetype_font_provider.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/text/text_metrics.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/utf8.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/value.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_booleans.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_children_separate.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_cli.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_control_flow.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_csg_tree.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_debug_hooks.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_dxf_svg_import.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_eval_context.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_export.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_extrude_roof.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_feature_detection.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_import_export.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_include_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_multi_color_merge.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_primitives.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_profiling.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_python_bindings.py +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_render_expr.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_scoping.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_surface.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_tail_calls.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_text.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_transforms.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_unexpected_args.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_use.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_value.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_viewport_params.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tests/test_zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tools/cli/cli_lib.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tools/cli/cli_lib.hpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/uv.lock +0 -0
|
@@ -152,7 +152,20 @@ struct IterList {
|
|
|
152
152
|
// (pre-redesign) behavior exactly.
|
|
153
153
|
struct VmFrame {
|
|
154
154
|
const CompiledChunk* chunk = nullptr;
|
|
155
|
-
|
|
155
|
+
// This frame's instruction stream, pre-decomposed into data()/size().
|
|
156
|
+
// driveVm's dispatch loop reads both once per INSTRUCTION; when this was a
|
|
157
|
+
// `const std::vector<Instruction>*`, that cost a pointer chase plus an
|
|
158
|
+
// end-minus-begin divided by sizeof(Instruction) (a multiply by a magic
|
|
159
|
+
// constant) on every opcode. ~11% of a whole Anklet.scad render sat in that
|
|
160
|
+
// loop preamble. A compiled chunk's code vector is immutable for as long as
|
|
161
|
+
// any frame runs it, so caching these is free -- but they must only ever be
|
|
162
|
+
// set together, hence setCode() rather than two public fields to forget.
|
|
163
|
+
const Instruction* code = nullptr;
|
|
164
|
+
size_t codeSize = 0;
|
|
165
|
+
void setCode(const std::vector<Instruction>& c) {
|
|
166
|
+
code = c.data();
|
|
167
|
+
codeSize = c.size();
|
|
168
|
+
}
|
|
156
169
|
size_t pc = 0;
|
|
157
170
|
std::vector<Value> slots;
|
|
158
171
|
std::vector<Value> stack;
|
|
@@ -189,6 +202,16 @@ struct VmFrame {
|
|
|
189
202
|
// brackets first", normally via matched Push/Pop, or via
|
|
190
203
|
// teardownVmCallStackDownTo on the exception path) already covers it.
|
|
191
204
|
std::vector<PendingCsgWrap> csgWrapStack;
|
|
205
|
+
// Scratch CallArgs for this frame's builtin/import call sites, reused
|
|
206
|
+
// across calls so its two vectors keep their capacity: building a fresh
|
|
207
|
+
// one per call was 1.99M of one Anklet.scad render's 10M allocations,
|
|
208
|
+
// second only to the argument vector this frame's operand stack now
|
|
209
|
+
// stands in for. One per FRAME rather than one per Evaluator because a
|
|
210
|
+
// builtin can re-enter the VM -- but only by pushing a new frame, which
|
|
211
|
+
// brings its own scratch, and a frame never has two call opcodes in
|
|
212
|
+
// flight at once. Frames themselves are pooled (acquireVmFrame), so the
|
|
213
|
+
// capacity survives the call that grew it.
|
|
214
|
+
CallArgs argScratch;
|
|
192
215
|
// The ORIGINAL callee name at push time, used by
|
|
193
216
|
// Evaluator::exitUserCallSuccess's own returnHook call when this frame
|
|
194
217
|
// carries a bracket -- deliberately NOT updated by a later tail hop
|
|
@@ -97,4 +97,14 @@ const oscad::Expression* argExpr(const oscad::Argument& arg);
|
|
|
97
97
|
// positional argument, not a fixed named slot.
|
|
98
98
|
std::vector<Value> allPositional(const CallArgs& args);
|
|
99
99
|
|
|
100
|
+
// allPositional()'s size and element access, without building the vector.
|
|
101
|
+
// The argument CHECKERS (function_builtins.cpp) only ever ask how many
|
|
102
|
+
// positional slots there are and look at a couple of them, so they used to
|
|
103
|
+
// pay a heap allocation plus a Value copy per slot on every builtin call
|
|
104
|
+
// that has a check entry -- 1.97M of the 16.6M allocations in one
|
|
105
|
+
// Anklet.scad render. positionalAt() answers undef for a gap, exactly as
|
|
106
|
+
// allPositional() pads one.
|
|
107
|
+
size_t positionalCount(const CallArgs& args);
|
|
108
|
+
const Value& positionalAt(const CallArgs& args, size_t pos);
|
|
109
|
+
|
|
100
110
|
} // namespace oscadeval
|
|
@@ -1812,7 +1812,26 @@ private:
|
|
|
1812
1812
|
// its (possibly many) active occurrences is checked, checking each
|
|
1813
1813
|
// DISTINCT X once is exactly equivalent to checking every occurrence
|
|
1814
1814
|
// -- not an approximation.
|
|
1815
|
-
|
|
1815
|
+
// A flat vector, not a map, for the reason the paragraph above already
|
|
1816
|
+
// establishes: the number of DISTINCT active declarations stays small and
|
|
1817
|
+
// roughly constant, so a linear scan beats hashing -- and an
|
|
1818
|
+
// unordered_map cost one node allocation per user call (595K in one
|
|
1819
|
+
// Anklet.scad render) where this costs none after warmup, while the
|
|
1820
|
+
// every-call containment scan above walks contiguous memory instead of a
|
|
1821
|
+
// hash table's buckets. Same flat-vector-over-small-map trade CallArgs and
|
|
1822
|
+
// BoundArgs already make. Entry order is not meaningful (the scan visits
|
|
1823
|
+
// all of them), so removal swaps with the back.
|
|
1824
|
+
std::vector<std::pair<const oscad::ASTNode*, int>> activeDeclRefcount_;
|
|
1825
|
+
// ++count for `decl`, appending an entry if it has none yet.
|
|
1826
|
+
void noteActiveDeclEnter(const oscad::ASTNode* declNode) {
|
|
1827
|
+
for (auto& entry : activeDeclRefcount_) {
|
|
1828
|
+
if (entry.first == declNode) {
|
|
1829
|
+
++entry.second;
|
|
1830
|
+
return;
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
activeDeclRefcount_.emplace_back(declNode, 1);
|
|
1834
|
+
}
|
|
1816
1835
|
|
|
1817
1836
|
// Shared cap on callStack_'s own size, checked by both
|
|
1818
1837
|
// evalUserFunctionCore (below) and evalUserModule (user_calls.cpp) --
|
|
@@ -12,37 +12,101 @@
|
|
|
12
12
|
|
|
13
13
|
namespace oscadeval {
|
|
14
14
|
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
// because this codebase has no escaping closures: a FunctionLiteral value
|
|
22
|
-
// is a bare AST pointer with no captured environment, and callCtxFor()
|
|
23
|
-
// re-derives every call's context from the LIVE call stack -- nothing ever
|
|
24
|
-
// reads a binding after the scope that pushed it has already exited.
|
|
15
|
+
// Recycles the blocks that TrailView/IndexedTrailView's own shared_ptrs are
|
|
16
|
+
// made of. Deriving one EvalContext opens three trail levels -- dyn, let_,
|
|
17
|
+
// dynPositions -- and each was a fresh make_shared: ~2M allocations in one
|
|
18
|
+
// Anklet.scad render, all of them the same size, almost all of them freed in
|
|
19
|
+
// reverse order a few microseconds later. This hands the same block straight
|
|
20
|
+
// back out.
|
|
25
21
|
//
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
//
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
22
|
+
// It changes WHERE the memory comes from and nothing else: no lifetime, no
|
|
23
|
+
// visibility, no popLevel timing. That is the whole point -- the trail's
|
|
24
|
+
// escaping-closure rules are the most delicate thing in this file, and an
|
|
25
|
+
// allocator cannot get them wrong.
|
|
26
|
+
//
|
|
27
|
+
// One size class, because there is exactly one: every block is the control
|
|
28
|
+
// block plus one view object. Anything else falls through to the global
|
|
29
|
+
// allocator rather than being kept.
|
|
30
|
+
//
|
|
31
|
+
// Worth ~1% of an Anklet.scad render, for 2M allocations removed -- a modest
|
|
32
|
+
// return, and deliberately recorded here as such: macOS's own small-object
|
|
33
|
+
// allocator is already a free list, so swapping it for another one only pays
|
|
34
|
+
// for the bookkeeping either side of it. Removing an allocation that also
|
|
35
|
+
// removed real work (a vector's worth of Value moves, say) has paid far
|
|
36
|
+
// better everywhere it has been tried in this codebase.
|
|
37
|
+
class ViewBlockPool {
|
|
38
|
+
public:
|
|
39
|
+
ViewBlockPool() { free_.reserve(kMaxKept); }
|
|
40
|
+
~ViewBlockPool() {
|
|
41
|
+
for (void* p : free_) ::operator delete(p);
|
|
42
|
+
}
|
|
43
|
+
ViewBlockPool(const ViewBlockPool&) = delete;
|
|
44
|
+
ViewBlockPool& operator=(const ViewBlockPool&) = delete;
|
|
45
|
+
|
|
46
|
+
void* take(std::size_t bytes) {
|
|
47
|
+
if (bytes == blockSize_ && !free_.empty()) {
|
|
48
|
+
void* p = free_.back();
|
|
49
|
+
free_.pop_back();
|
|
50
|
+
return p;
|
|
51
|
+
}
|
|
52
|
+
if (blockSize_ == 0) blockSize_ = bytes;
|
|
53
|
+
return ::operator new(bytes);
|
|
54
|
+
}
|
|
55
|
+
// noexcept is safe: free_ was reserved to kMaxKept up front and is never
|
|
56
|
+
// pushed past it, so this push_back cannot reallocate and cannot throw.
|
|
57
|
+
void give(void* p, std::size_t bytes) noexcept {
|
|
58
|
+
if (bytes != blockSize_ || free_.size() >= kMaxKept) {
|
|
59
|
+
::operator delete(p);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
free_.push_back(p);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private:
|
|
66
|
+
static constexpr std::size_t kMaxKept = 512;
|
|
67
|
+
std::size_t blockSize_ = 0;
|
|
68
|
+
std::vector<void*> free_;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// A STATELESS allocator over one pool per view type (each type has exactly
|
|
72
|
+
// one block size, so each gets its own single-size-class pool). Stateless
|
|
73
|
+
// matters twice over: std::allocate_shared stores a copy of the allocator
|
|
74
|
+
// inside the very block it allocated, so a stateful one both grows every
|
|
75
|
+
// block and -- if it held a shared_ptr to keep the pool alive past the last
|
|
76
|
+
// view, which a pool owned by the storage would need -- pays an atomic
|
|
77
|
+
// refcount pair per allocation. That version was measured, and it was SLOWER
|
|
78
|
+
// than not pooling at all.
|
|
79
|
+
//
|
|
80
|
+
// thread_local, so no locking and no cross-thread sharing, and it outlives
|
|
81
|
+
// every view on its thread, which is what makes "keep the pool alive for the
|
|
82
|
+
// final deallocate" a non-problem rather than a lifetime puzzle.
|
|
83
|
+
template <typename T>
|
|
84
|
+
class ViewBlockAllocator {
|
|
85
|
+
public:
|
|
86
|
+
using value_type = T;
|
|
87
|
+
ViewBlockAllocator() = default;
|
|
88
|
+
template <typename U>
|
|
89
|
+
ViewBlockAllocator(const ViewBlockAllocator<U>&) {}
|
|
90
|
+
|
|
91
|
+
T* allocate(std::size_t n) { return static_cast<T*>(pool().take(n * sizeof(T))); }
|
|
92
|
+
void deallocate(T* p, std::size_t n) noexcept { pool().give(p, n * sizeof(T)); }
|
|
93
|
+
|
|
94
|
+
template <typename U>
|
|
95
|
+
bool operator==(const ViewBlockAllocator<U>&) const noexcept {
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
template <typename U>
|
|
99
|
+
bool operator!=(const ViewBlockAllocator<U>&) const noexcept {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
private:
|
|
104
|
+
static ViewBlockPool& pool() {
|
|
105
|
+
static thread_local ViewBlockPool p;
|
|
106
|
+
return p;
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
46
110
|
template <typename T>
|
|
47
111
|
class ScopeTrailStorage {
|
|
48
112
|
public:
|
|
@@ -50,7 +114,7 @@ public:
|
|
|
50
114
|
// ancestry chain here (an isolating derivation -- see openChild).
|
|
51
115
|
int openLevel(int parentLevel) {
|
|
52
116
|
int level = ++nextLevel_;
|
|
53
|
-
parent_
|
|
117
|
+
parent_.push_back(parentLevel); // index == level; see parent_'s own comment
|
|
54
118
|
return level;
|
|
55
119
|
}
|
|
56
120
|
|
|
@@ -122,7 +186,7 @@ public:
|
|
|
122
186
|
}
|
|
123
187
|
dirty_.erase(it);
|
|
124
188
|
}
|
|
125
|
-
parent_
|
|
189
|
+
parent_[static_cast<size_t>(level)] = 0; // dead: an ancestry walk stops here
|
|
126
190
|
}
|
|
127
191
|
|
|
128
192
|
// nullptr if `name` has no binding on `myLevel`'s own ancestry chain.
|
|
@@ -154,8 +218,7 @@ public:
|
|
|
154
218
|
} else if (entryLevel == ancestor) {
|
|
155
219
|
return &vec[static_cast<size_t>(idx)].value;
|
|
156
220
|
} else {
|
|
157
|
-
|
|
158
|
-
ancestor = pit != parent_.end() ? pit->second : 0;
|
|
221
|
+
ancestor = parent_[static_cast<size_t>(ancestor)];
|
|
159
222
|
}
|
|
160
223
|
}
|
|
161
224
|
return nullptr;
|
|
@@ -194,8 +257,21 @@ private:
|
|
|
194
257
|
};
|
|
195
258
|
std::unordered_map<std::string, std::vector<Entry>> stacks_;
|
|
196
259
|
std::unordered_map<int, std::vector<std::string>> dirty_;
|
|
197
|
-
|
|
260
|
+
// level -> parent level (0 = chain terminates here, which is also what a
|
|
261
|
+
// popped level reads back as). Levels come from `++nextLevel_`, so they are
|
|
262
|
+
// dense and monotonic and this is a plain vector indexed BY level, with
|
|
263
|
+
// element 0 the unused stand-in for "no parent" -- push_back in openLevel()
|
|
264
|
+
// keeps index == level. It used to be an unordered_map<int,int>, which cost
|
|
265
|
+
// one hash-node allocation per scope derivation (3 of the 10 allocations a
|
|
266
|
+
// user function call makes, ~2M of them in one Anklet.scad render) and made
|
|
267
|
+
// lookup()'s ancestry walk -- run on every variable read -- a hash probe per
|
|
268
|
+
// hop instead of an array index. It never shrinks: 4 bytes per level ever
|
|
269
|
+
// opened (~2.6MB for Anklet.scad), traded knowingly for the allocation.
|
|
270
|
+
// Levels are NEVER renumbered or reused -- lookup()'s sorted-merge walk
|
|
271
|
+
// depends on level numbers being globally monotonic.
|
|
272
|
+
std::vector<int> parent_{0};
|
|
198
273
|
int nextLevel_ = 0;
|
|
274
|
+
|
|
199
275
|
};
|
|
200
276
|
|
|
201
277
|
// Per-EvalContext handle onto a shared ScopeTrailStorage<T>: this view's
|
|
@@ -224,7 +300,8 @@ public:
|
|
|
224
300
|
static std::shared_ptr<TrailView<T>> makeRoot() {
|
|
225
301
|
auto storage = std::make_shared<ScopeTrailStorage<T>>();
|
|
226
302
|
int level = storage->openLevel(0);
|
|
227
|
-
return std::
|
|
303
|
+
return std::allocate_shared<TrailView<T>>(ViewBlockAllocator<TrailView<T>>(), storage,
|
|
304
|
+
level);
|
|
228
305
|
}
|
|
229
306
|
|
|
230
307
|
// Open a fresh level for writes. `isolate=true` terminates the new
|
|
@@ -249,7 +326,7 @@ public:
|
|
|
249
326
|
// call returns; ~TrailView() pops ITS bindings from ScopeTrailStorage
|
|
250
327
|
// (erasing the very data the still-alive child's ancestry walk needs)
|
|
251
328
|
// even though the walk can still numerically reach that ancestor level
|
|
252
|
-
// via ScopeTrailStorage::parent_ (that
|
|
329
|
+
// via ScopeTrailStorage::parent_ (that entry is untouched -- only
|
|
253
330
|
// the DATA is gone). Caught by a closure created inside a let()
|
|
254
331
|
// nested one level inside its own enclosing call reading undef for a
|
|
255
332
|
// variable bound at the call's own (now-popped) level, not the let()'s
|
|
@@ -261,7 +338,8 @@ public:
|
|
|
261
338
|
// changes what happens when something holds an EXTRA reference.
|
|
262
339
|
std::shared_ptr<TrailView<T>> openChild(bool isolate) const {
|
|
263
340
|
int level = storage_->openLevel(isolate ? 0 : level_);
|
|
264
|
-
auto child = std::
|
|
341
|
+
auto child = std::allocate_shared<TrailView<T>>(ViewBlockAllocator<TrailView<T>>(),
|
|
342
|
+
storage_, level);
|
|
265
343
|
if (!isolate) child->parentView_ = this->shared_from_this();
|
|
266
344
|
return child;
|
|
267
345
|
}
|
|
@@ -344,7 +422,7 @@ public:
|
|
|
344
422
|
|
|
345
423
|
int openLevel(int parentLevel) {
|
|
346
424
|
int level = ++nextLevel_;
|
|
347
|
-
parent_
|
|
425
|
+
parent_.push_back(parentLevel); // index == level; see parent_'s own comment
|
|
348
426
|
return level;
|
|
349
427
|
}
|
|
350
428
|
|
|
@@ -395,7 +473,7 @@ public:
|
|
|
395
473
|
}
|
|
396
474
|
dirty_.erase(it);
|
|
397
475
|
}
|
|
398
|
-
parent_
|
|
476
|
+
parent_[static_cast<size_t>(level)] = 0; // dead: an ancestry walk stops here
|
|
399
477
|
}
|
|
400
478
|
|
|
401
479
|
// Same sorted-merge ancestry walk as ScopeTrailStorage::lookup -- see
|
|
@@ -414,8 +492,7 @@ public:
|
|
|
414
492
|
} else if (entryLevel == ancestor) {
|
|
415
493
|
return &vec[static_cast<size_t>(idx)].value;
|
|
416
494
|
} else {
|
|
417
|
-
|
|
418
|
-
ancestor = pit != parent_.end() ? pit->second : 0;
|
|
495
|
+
ancestor = parent_[static_cast<size_t>(ancestor)];
|
|
419
496
|
}
|
|
420
497
|
}
|
|
421
498
|
return nullptr;
|
|
@@ -450,8 +527,9 @@ private:
|
|
|
450
527
|
std::shared_ptr<DynNameIntern> intern_;
|
|
451
528
|
std::vector<std::vector<Entry>> stacks_;
|
|
452
529
|
std::unordered_map<int, std::vector<int>> dirty_;
|
|
453
|
-
std::
|
|
530
|
+
std::vector<int> parent_{0}; // see ScopeTrailStorage::parent_
|
|
454
531
|
int nextLevel_ = 0;
|
|
532
|
+
|
|
455
533
|
};
|
|
456
534
|
|
|
457
535
|
// Per-EvalContext handle onto a shared IndexedScopeTrailStorage<T> -- the
|
|
@@ -464,12 +542,14 @@ public:
|
|
|
464
542
|
static std::shared_ptr<IndexedTrailView<T>> makeRoot(std::shared_ptr<DynNameIntern> intern) {
|
|
465
543
|
auto storage = std::make_shared<IndexedScopeTrailStorage<T>>(std::move(intern));
|
|
466
544
|
int level = storage->openLevel(0);
|
|
467
|
-
return std::
|
|
545
|
+
return std::allocate_shared<IndexedTrailView<T>>(
|
|
546
|
+
ViewBlockAllocator<IndexedTrailView<T>>(), storage, level);
|
|
468
547
|
}
|
|
469
548
|
|
|
470
549
|
std::shared_ptr<IndexedTrailView<T>> openChild(bool isolate) const {
|
|
471
550
|
int level = storage_->openLevel(isolate ? 0 : level_);
|
|
472
|
-
return std::
|
|
551
|
+
return std::allocate_shared<IndexedTrailView<T>>(
|
|
552
|
+
ViewBlockAllocator<IndexedTrailView<T>>(), storage_, level);
|
|
473
553
|
}
|
|
474
554
|
|
|
475
555
|
IndexedTrailView(std::shared_ptr<IndexedScopeTrailStorage<T>> storage, int level)
|
|
@@ -106,6 +106,18 @@ const oscad::Expression* argExpr(const oscad::Argument& arg) {
|
|
|
106
106
|
return static_cast<const oscad::PositionalArgument&>(arg).expr.get();
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
size_t positionalCount(const CallArgs& args) {
|
|
110
|
+
int maxPos = -1;
|
|
111
|
+
for (const auto& [idx, v] : args.positional) maxPos = std::max(maxPos, idx);
|
|
112
|
+
return static_cast<size_t>(maxPos + 1);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const Value& positionalAt(const CallArgs& args, size_t pos) {
|
|
116
|
+
static const Value kUndef;
|
|
117
|
+
const Value* v = args.findPositional(static_cast<int>(pos));
|
|
118
|
+
return v ? *v : kUndef;
|
|
119
|
+
}
|
|
120
|
+
|
|
109
121
|
std::vector<Value> allPositional(const CallArgs& args) {
|
|
110
122
|
int maxPos = -1;
|
|
111
123
|
for (const auto& [idx, v] : args.positional) maxPos = std::max(maxPos, idx);
|
{openscad_cpp_evaluator-1.5.0 → openscad_cpp_evaluator-1.6.1}/src/builtins/function_builtins.cpp
RENAMED
|
@@ -1179,15 +1179,15 @@ void warnConversion(Evaluator& ev, const std::string& name, const std::string& w
|
|
|
1179
1179
|
// numbers, with a distinct "at least 1 vector element" arity text for the
|
|
1180
1180
|
// empty-vector case.
|
|
1181
1181
|
bool checkMinMax(Evaluator& ev, const std::string& name, const CallArgs& args, const oscad::Position* pos) {
|
|
1182
|
-
const
|
|
1183
|
-
const size_t count =
|
|
1182
|
+
const size_t nPos = positionalCount(args);
|
|
1183
|
+
const size_t count = nPos + args.named.size();
|
|
1184
1184
|
if (count < 1) {
|
|
1185
1185
|
warnArity(ev, name, "at least 1", count, pos);
|
|
1186
1186
|
return false;
|
|
1187
1187
|
}
|
|
1188
|
-
if (
|
|
1188
|
+
if (nPos == 1 && std::holds_alternative<ListPtr>(positionalAt(args, 0))) {
|
|
1189
1189
|
static const std::vector<Value> kEmptyItems;
|
|
1190
|
-
const ListPtr& l = std::get<ListPtr>(
|
|
1190
|
+
const ListPtr& l = std::get<ListPtr>(positionalAt(args, 0));
|
|
1191
1191
|
const std::vector<Value>& items = l ? l->items : kEmptyItems;
|
|
1192
1192
|
if (items.empty()) {
|
|
1193
1193
|
warnArity(ev, name, "at least 1 vector element", 0, pos);
|
|
@@ -1201,9 +1201,9 @@ bool checkMinMax(Evaluator& ev, const std::string& name, const CallArgs& args, c
|
|
|
1201
1201
|
}
|
|
1202
1202
|
return true;
|
|
1203
1203
|
}
|
|
1204
|
-
for (size_t i = 0; i <
|
|
1205
|
-
if (!std::holds_alternative<double>(
|
|
1206
|
-
warnConversion(ev, name, "argument " + std::to_string(i), "number",
|
|
1204
|
+
for (size_t i = 0; i < nPos; ++i) {
|
|
1205
|
+
if (!std::holds_alternative<double>(positionalAt(args, i))) {
|
|
1206
|
+
warnConversion(ev, name, "argument " + std::to_string(i), "number", positionalAt(args, i), pos);
|
|
1207
1207
|
return false;
|
|
1208
1208
|
}
|
|
1209
1209
|
}
|
|
@@ -1219,8 +1219,8 @@ bool checkBuiltinArgs(Evaluator& ev, const std::string& name, BuiltinFnId id, co
|
|
|
1219
1219
|
if (it == checks.end()) return true;
|
|
1220
1220
|
const BuiltinCheck& c = it->second;
|
|
1221
1221
|
|
|
1222
|
-
const
|
|
1223
|
-
const size_t count =
|
|
1222
|
+
const size_t nPos = positionalCount(args);
|
|
1223
|
+
const size_t count = nPos + args.named.size();
|
|
1224
1224
|
if (c.arityText && (static_cast<int>(count) < c.minArgs || (c.maxArgs >= 0 && static_cast<int>(count) > c.maxArgs))) {
|
|
1225
1225
|
warnArity(ev, name, c.arityText, count, pos);
|
|
1226
1226
|
return false;
|
|
@@ -1229,9 +1229,10 @@ bool checkBuiltinArgs(Evaluator& ev, const std::string& name, BuiltinFnId id, co
|
|
|
1229
1229
|
// flat argument list can't be reconstructed from our split
|
|
1230
1230
|
// positional/named form, and warning on the wrong index would be worse
|
|
1231
1231
|
// than staying quiet on a spelling nobody uses for these builtins.
|
|
1232
|
-
for (size_t i = 0; i < c.types.size() && i <
|
|
1233
|
-
|
|
1234
|
-
|
|
1232
|
+
for (size_t i = 0; i < c.types.size() && i < nPos; ++i) {
|
|
1233
|
+
const Value& v = positionalAt(args, i);
|
|
1234
|
+
if (!(typeBit(v) & c.types[i].allowed)) {
|
|
1235
|
+
warnConversion(ev, name, "argument " + std::to_string(i), c.types[i].expected, v, pos);
|
|
1235
1236
|
return false;
|
|
1236
1237
|
}
|
|
1237
1238
|
}
|