openscad-cpp-evaluator 1.4.1__tar.gz → 1.6.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.4.1 → openscad_cpp_evaluator-1.6.0}/PKG-INFO +1 -1
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/bytecode_vm.hpp +24 -1
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/call_args.hpp +10 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/evaluator.hpp +20 -1
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/scope_trail.hpp +21 -11
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/utf8.hpp +6 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/pyproject.toml +1 -1
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/builtins/call_args.cpp +12 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/builtins/function_builtins.cpp +15 -35
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/bytecode_vm.cpp +46 -43
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/user_calls.cpp +11 -5
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/utf8.cpp +20 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/value.cpp +84 -7
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_bytecode_compiler.cpp +35 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_scope_trail.cpp +24 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_value.cpp +106 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/.github/workflows/wheels.yml +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/.gitignore +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/.gitmodules +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/LICENSE +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/README.md +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/bindings/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/bindings/ast_to_py.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/bindings/module.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/cmake/embed_font.cmake +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/examples/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/examples/eval_perf_benchmark.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/examples/manifold_cache_reuse.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/examples/minimal_debugger.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/.gitignore +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/README.md +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope_table.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/src/api.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/src/comments.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/src/position.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/src/scope.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/tests/test_render_expression.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/bytecode.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/colored_body.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/export.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/font_match.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/format_closure.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/freetype_font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/mesh_check.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/profile.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/segments.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/value.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/python/openscad_cpp_evaluator/__init__.py +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/resources/fonts/LICENSE +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/resources/fonts/LiberationSans-Regular.ttf +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/builtins/booleans.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/builtins/builtins.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/builtins/color.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/builtins/control.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/builtins/dxf_dim.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/builtins/extrude.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/builtins/import.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/builtins/modifiers.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/builtins/primitives_2d.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/builtins/primitives_3d.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/builtins/registry.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/builtins/roof.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/builtins/segments.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/builtins/surface.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/builtins/text.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/builtins/topology.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/builtins/transforms.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/colored_body.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/csg_generate.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/csg_resolve.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/css_colors.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/debug/debug_repl.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/debug_profile.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/eval_context.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/eval_error.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/eval_use.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/export.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/format_closure.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/import/dxf_import.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/import/mesh_import.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/import/surface_load.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/import/svg_import.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/measure_geometry.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/stmt_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/text/font_match.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/text/freetype_font_provider.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/text/text_metrics.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/src/zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_booleans.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_children_separate.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_cli.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_control_flow.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_csg_tree.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_debug_hooks.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_dxf_svg_import.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_eval_context.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_export.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_extrude_roof.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_feature_detection.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_import_export.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_include_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_multi_color_merge.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_primitives.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_profiling.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_python_bindings.py +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_render_expr.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_scoping.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_surface.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_tail_calls.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_text.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_transforms.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_unexpected_args.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_use.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_viewport_params.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tests/test_zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tools/cli/cli_lib.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tools/cli/cli_lib.hpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-1.4.1 → openscad_cpp_evaluator-1.6.0}/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) --
|
|
@@ -50,7 +50,7 @@ public:
|
|
|
50
50
|
// ancestry chain here (an isolating derivation -- see openChild).
|
|
51
51
|
int openLevel(int parentLevel) {
|
|
52
52
|
int level = ++nextLevel_;
|
|
53
|
-
parent_
|
|
53
|
+
parent_.push_back(parentLevel); // index == level; see parent_'s own comment
|
|
54
54
|
return level;
|
|
55
55
|
}
|
|
56
56
|
|
|
@@ -122,7 +122,7 @@ public:
|
|
|
122
122
|
}
|
|
123
123
|
dirty_.erase(it);
|
|
124
124
|
}
|
|
125
|
-
parent_
|
|
125
|
+
parent_[static_cast<size_t>(level)] = 0; // dead: an ancestry walk stops here
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
// nullptr if `name` has no binding on `myLevel`'s own ancestry chain.
|
|
@@ -154,8 +154,7 @@ public:
|
|
|
154
154
|
} else if (entryLevel == ancestor) {
|
|
155
155
|
return &vec[static_cast<size_t>(idx)].value;
|
|
156
156
|
} else {
|
|
157
|
-
|
|
158
|
-
ancestor = pit != parent_.end() ? pit->second : 0;
|
|
157
|
+
ancestor = parent_[static_cast<size_t>(ancestor)];
|
|
159
158
|
}
|
|
160
159
|
}
|
|
161
160
|
return nullptr;
|
|
@@ -194,7 +193,19 @@ private:
|
|
|
194
193
|
};
|
|
195
194
|
std::unordered_map<std::string, std::vector<Entry>> stacks_;
|
|
196
195
|
std::unordered_map<int, std::vector<std::string>> dirty_;
|
|
197
|
-
|
|
196
|
+
// level -> parent level (0 = chain terminates here, which is also what a
|
|
197
|
+
// popped level reads back as). Levels come from `++nextLevel_`, so they are
|
|
198
|
+
// dense and monotonic and this is a plain vector indexed BY level, with
|
|
199
|
+
// element 0 the unused stand-in for "no parent" -- push_back in openLevel()
|
|
200
|
+
// keeps index == level. It used to be an unordered_map<int,int>, which cost
|
|
201
|
+
// one hash-node allocation per scope derivation (3 of the 10 allocations a
|
|
202
|
+
// user function call makes, ~2M of them in one Anklet.scad render) and made
|
|
203
|
+
// lookup()'s ancestry walk -- run on every variable read -- a hash probe per
|
|
204
|
+
// hop instead of an array index. It never shrinks: 4 bytes per level ever
|
|
205
|
+
// opened (~2.6MB for Anklet.scad), traded knowingly for the allocation.
|
|
206
|
+
// Levels are NEVER renumbered or reused -- lookup()'s sorted-merge walk
|
|
207
|
+
// depends on level numbers being globally monotonic.
|
|
208
|
+
std::vector<int> parent_{0};
|
|
198
209
|
int nextLevel_ = 0;
|
|
199
210
|
};
|
|
200
211
|
|
|
@@ -249,7 +260,7 @@ public:
|
|
|
249
260
|
// call returns; ~TrailView() pops ITS bindings from ScopeTrailStorage
|
|
250
261
|
// (erasing the very data the still-alive child's ancestry walk needs)
|
|
251
262
|
// even though the walk can still numerically reach that ancestor level
|
|
252
|
-
// via ScopeTrailStorage::parent_ (that
|
|
263
|
+
// via ScopeTrailStorage::parent_ (that entry is untouched -- only
|
|
253
264
|
// the DATA is gone). Caught by a closure created inside a let()
|
|
254
265
|
// nested one level inside its own enclosing call reading undef for a
|
|
255
266
|
// variable bound at the call's own (now-popped) level, not the let()'s
|
|
@@ -344,7 +355,7 @@ public:
|
|
|
344
355
|
|
|
345
356
|
int openLevel(int parentLevel) {
|
|
346
357
|
int level = ++nextLevel_;
|
|
347
|
-
parent_
|
|
358
|
+
parent_.push_back(parentLevel); // index == level; see parent_'s own comment
|
|
348
359
|
return level;
|
|
349
360
|
}
|
|
350
361
|
|
|
@@ -395,7 +406,7 @@ public:
|
|
|
395
406
|
}
|
|
396
407
|
dirty_.erase(it);
|
|
397
408
|
}
|
|
398
|
-
parent_
|
|
409
|
+
parent_[static_cast<size_t>(level)] = 0; // dead: an ancestry walk stops here
|
|
399
410
|
}
|
|
400
411
|
|
|
401
412
|
// Same sorted-merge ancestry walk as ScopeTrailStorage::lookup -- see
|
|
@@ -414,8 +425,7 @@ public:
|
|
|
414
425
|
} else if (entryLevel == ancestor) {
|
|
415
426
|
return &vec[static_cast<size_t>(idx)].value;
|
|
416
427
|
} else {
|
|
417
|
-
|
|
418
|
-
ancestor = pit != parent_.end() ? pit->second : 0;
|
|
428
|
+
ancestor = parent_[static_cast<size_t>(ancestor)];
|
|
419
429
|
}
|
|
420
430
|
}
|
|
421
431
|
return nullptr;
|
|
@@ -450,7 +460,7 @@ private:
|
|
|
450
460
|
std::shared_ptr<DynNameIntern> intern_;
|
|
451
461
|
std::vector<std::vector<Entry>> stacks_;
|
|
452
462
|
std::unordered_map<int, std::vector<int>> dirty_;
|
|
453
|
-
std::
|
|
463
|
+
std::vector<int> parent_{0}; // see ScopeTrailStorage::parent_
|
|
454
464
|
int nextLevel_ = 0;
|
|
455
465
|
};
|
|
456
466
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
+
#include <cstdint>
|
|
3
4
|
#include <string>
|
|
4
5
|
#include <vector>
|
|
5
6
|
|
|
@@ -17,6 +18,11 @@ namespace oscadeval {
|
|
|
17
18
|
// string that actually holds non-ASCII pays, and those are short in
|
|
18
19
|
// practice.
|
|
19
20
|
|
|
21
|
+
// One code point as UTF-8. The caller decides which code points are
|
|
22
|
+
// legal -- chr() drops an invalid one, a \uXXXX escape substitutes a space
|
|
23
|
+
// -- so this encodes whatever it is given.
|
|
24
|
+
std::string utf8Encode(uint32_t cp);
|
|
25
|
+
|
|
20
26
|
// True when every byte is < 0x80, so byte offsets and character offsets are
|
|
21
27
|
// the same thing.
|
|
22
28
|
bool utf8IsAscii(const std::string& s);
|
|
@@ -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.4.1 → openscad_cpp_evaluator-1.6.0}/src/builtins/function_builtins.cpp
RENAMED
|
@@ -193,29 +193,8 @@ double atan2Degrees(double y, double x) {
|
|
|
193
193
|
return std::fabs(degs - whole) < 3.0E-14 ? whole : degs;
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
-
//
|
|
197
|
-
//
|
|
198
|
-
// handling, not a raw byte cast.
|
|
199
|
-
std::string utf8Encode(uint32_t cp) {
|
|
200
|
-
std::string out;
|
|
201
|
-
if (cp <= 0x7F) {
|
|
202
|
-
out.push_back(static_cast<char>(cp));
|
|
203
|
-
} else if (cp <= 0x7FF) {
|
|
204
|
-
out.push_back(static_cast<char>(0xC0 | (cp >> 6)));
|
|
205
|
-
out.push_back(static_cast<char>(0x80 | (cp & 0x3F)));
|
|
206
|
-
} else if (cp <= 0xFFFF) {
|
|
207
|
-
out.push_back(static_cast<char>(0xE0 | (cp >> 12)));
|
|
208
|
-
out.push_back(static_cast<char>(0x80 | ((cp >> 6) & 0x3F)));
|
|
209
|
-
out.push_back(static_cast<char>(0x80 | (cp & 0x3F)));
|
|
210
|
-
} else {
|
|
211
|
-
out.push_back(static_cast<char>(0xF0 | (cp >> 18)));
|
|
212
|
-
out.push_back(static_cast<char>(0x80 | ((cp >> 12) & 0x3F)));
|
|
213
|
-
out.push_back(static_cast<char>(0x80 | ((cp >> 6) & 0x3F)));
|
|
214
|
-
out.push_back(static_cast<char>(0x80 | (cp & 0x3F)));
|
|
215
|
-
}
|
|
216
|
-
return out;
|
|
217
|
-
}
|
|
218
|
-
|
|
196
|
+
// utf8Encode lives in utf8.cpp -- the string-literal escape decoder
|
|
197
|
+
// (\uXXXX) needs it too.
|
|
219
198
|
uint32_t utf8DecodeFirst(const std::string& s) {
|
|
220
199
|
if (s.empty()) return 0;
|
|
221
200
|
const auto b = [&](size_t i) { return static_cast<unsigned char>(s[i]); };
|
|
@@ -1200,15 +1179,15 @@ void warnConversion(Evaluator& ev, const std::string& name, const std::string& w
|
|
|
1200
1179
|
// numbers, with a distinct "at least 1 vector element" arity text for the
|
|
1201
1180
|
// empty-vector case.
|
|
1202
1181
|
bool checkMinMax(Evaluator& ev, const std::string& name, const CallArgs& args, const oscad::Position* pos) {
|
|
1203
|
-
const
|
|
1204
|
-
const size_t count =
|
|
1182
|
+
const size_t nPos = positionalCount(args);
|
|
1183
|
+
const size_t count = nPos + args.named.size();
|
|
1205
1184
|
if (count < 1) {
|
|
1206
1185
|
warnArity(ev, name, "at least 1", count, pos);
|
|
1207
1186
|
return false;
|
|
1208
1187
|
}
|
|
1209
|
-
if (
|
|
1188
|
+
if (nPos == 1 && std::holds_alternative<ListPtr>(positionalAt(args, 0))) {
|
|
1210
1189
|
static const std::vector<Value> kEmptyItems;
|
|
1211
|
-
const ListPtr& l = std::get<ListPtr>(
|
|
1190
|
+
const ListPtr& l = std::get<ListPtr>(positionalAt(args, 0));
|
|
1212
1191
|
const std::vector<Value>& items = l ? l->items : kEmptyItems;
|
|
1213
1192
|
if (items.empty()) {
|
|
1214
1193
|
warnArity(ev, name, "at least 1 vector element", 0, pos);
|
|
@@ -1222,9 +1201,9 @@ bool checkMinMax(Evaluator& ev, const std::string& name, const CallArgs& args, c
|
|
|
1222
1201
|
}
|
|
1223
1202
|
return true;
|
|
1224
1203
|
}
|
|
1225
|
-
for (size_t i = 0; i <
|
|
1226
|
-
if (!std::holds_alternative<double>(
|
|
1227
|
-
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);
|
|
1228
1207
|
return false;
|
|
1229
1208
|
}
|
|
1230
1209
|
}
|
|
@@ -1240,8 +1219,8 @@ bool checkBuiltinArgs(Evaluator& ev, const std::string& name, BuiltinFnId id, co
|
|
|
1240
1219
|
if (it == checks.end()) return true;
|
|
1241
1220
|
const BuiltinCheck& c = it->second;
|
|
1242
1221
|
|
|
1243
|
-
const
|
|
1244
|
-
const size_t count =
|
|
1222
|
+
const size_t nPos = positionalCount(args);
|
|
1223
|
+
const size_t count = nPos + args.named.size();
|
|
1245
1224
|
if (c.arityText && (static_cast<int>(count) < c.minArgs || (c.maxArgs >= 0 && static_cast<int>(count) > c.maxArgs))) {
|
|
1246
1225
|
warnArity(ev, name, c.arityText, count, pos);
|
|
1247
1226
|
return false;
|
|
@@ -1250,9 +1229,10 @@ bool checkBuiltinArgs(Evaluator& ev, const std::string& name, BuiltinFnId id, co
|
|
|
1250
1229
|
// flat argument list can't be reconstructed from our split
|
|
1251
1230
|
// positional/named form, and warning on the wrong index would be worse
|
|
1252
1231
|
// than staying quiet on a spelling nobody uses for these builtins.
|
|
1253
|
-
for (size_t i = 0; i < c.types.size() && i <
|
|
1254
|
-
|
|
1255
|
-
|
|
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);
|
|
1256
1236
|
return false;
|
|
1257
1237
|
}
|
|
1258
1238
|
}
|
|
@@ -20,10 +20,18 @@ namespace {
|
|
|
20
20
|
|
|
21
21
|
// Shared by Op::CallFn's isBuiltin (evalBuiltinFunction) and isImport
|
|
22
22
|
// (importAsValue) branches -- both take the same pre-resolved CallArgs
|
|
23
|
-
// shape resolveArgs would build for the interpreter path. `args`
|
|
24
|
-
//
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
// shape resolveArgs would build for the interpreter path. `args` points
|
|
24
|
+
// AT THE CALLER FRAME'S OPERAND STACK, not at a copy: the arguments are
|
|
25
|
+
// already sitting there contiguously and in order, so every Op::Call*
|
|
26
|
+
// hands over `f.stack.data() + argBase` and truncates the stack once the
|
|
27
|
+
// arguments have been moved out. Building a `std::vector<Value>` for them
|
|
28
|
+
// instead was the single largest allocation site in the whole evaluator --
|
|
29
|
+
// 2.57M of one Anklet.scad render's 12.7M allocations, one per function
|
|
30
|
+
// call, builtins included. `args` is consumed (each element moved out), and
|
|
31
|
+
// nothing may push to that stack until it has been.
|
|
32
|
+
CallArgs& buildCallArgs(const CompiledChunk::CallSite& site, Value* args, size_t argCount, CallArgs& callArgs) {
|
|
33
|
+
callArgs.positional.clear();
|
|
34
|
+
callArgs.named.clear();
|
|
27
35
|
int positionalIdx = 0;
|
|
28
36
|
for (size_t i = 0; i < argCount; ++i) {
|
|
29
37
|
if (site.argNames[i]) {
|
|
@@ -41,7 +49,7 @@ CallArgs buildCallArgs(const CompiledChunk::CallSite& site, std::vector<Value>&
|
|
|
41
49
|
// LIST is `paramNames` (in declared order -- a FunctionDeclaration's
|
|
42
50
|
// parameters or a FunctionLiteral's). Shared by CallFn/CallFnTail (a
|
|
43
51
|
// site.decl callee) and CallDynamic/CallDynamicTail (a closure callee).
|
|
44
|
-
BoundArgs buildBoundArgs(Evaluator& ev, const CompiledChunk::CallSite& site,
|
|
52
|
+
BoundArgs buildBoundArgs(Evaluator& ev, const CompiledChunk::CallSite& site, Value* args, size_t argCount,
|
|
45
53
|
const std::vector<std::unique_ptr<oscad::ParameterDeclaration>>& paramNames) {
|
|
46
54
|
BoundArgs bound;
|
|
47
55
|
bound.reserve(argCount);
|
|
@@ -176,7 +184,7 @@ void applyCompiledDefaultsToFrame(Evaluator& ev, const CompiledChunk& chunk, VmF
|
|
|
176
184
|
if (!chunk.defaultCode[i].empty()) {
|
|
177
185
|
auto defaultFrame = ev.acquireVmFrame();
|
|
178
186
|
defaultFrame->chunk = &chunk;
|
|
179
|
-
defaultFrame->
|
|
187
|
+
defaultFrame->setCode(chunk.defaultCode[i]);
|
|
180
188
|
defaultFrame->pc = 0;
|
|
181
189
|
defaultFrame->slots = frame.slots; // defaults may read earlier SIBLING slots? no -- compiled with an
|
|
182
190
|
// isolated (zero-frame) scope, see bytecode_compiler.cpp's
|
|
@@ -213,7 +221,7 @@ void pushBareFrame(Evaluator& ev, const CompiledChunk& chunk, const std::vector<
|
|
|
213
221
|
EvalContext ctx) {
|
|
214
222
|
auto frame = ev.acquireVmFrame();
|
|
215
223
|
frame->chunk = &chunk;
|
|
216
|
-
frame->code
|
|
224
|
+
frame->setCode(code);
|
|
217
225
|
frame->pc = 0;
|
|
218
226
|
frame->slots.assign(static_cast<size_t>(chunk.numSlots), Value{});
|
|
219
227
|
frame->stack.clear();
|
|
@@ -254,7 +262,7 @@ void pushBracketedCallFrame(Evaluator& ev, const CompiledChunk& chunk, const osc
|
|
|
254
262
|
|
|
255
263
|
auto frame = ev.acquireVmFrame();
|
|
256
264
|
frame->chunk = &chunk;
|
|
257
|
-
frame->
|
|
265
|
+
frame->setCode(chunk.bodyCode);
|
|
258
266
|
frame->pc = 0;
|
|
259
267
|
frame->slots.assign(static_cast<size_t>(chunk.numSlots), Value{});
|
|
260
268
|
frame->stack.clear();
|
|
@@ -314,7 +322,7 @@ void pushBracketedModuleFrame(Evaluator& ev, const CompiledChunk& chunk, const o
|
|
|
314
322
|
}
|
|
315
323
|
auto frame = ev.acquireVmFrame();
|
|
316
324
|
frame->chunk = &chunk;
|
|
317
|
-
frame->
|
|
325
|
+
frame->setCode(chunk.bodyCode);
|
|
318
326
|
frame->pc = 0;
|
|
319
327
|
// See runCompiledModuleBody's own doc comment (below) for why this is
|
|
320
328
|
// .assign(numSlots) now, not .clear() -- a nested let-expression
|
|
@@ -369,7 +377,7 @@ void pushChildrenForwardFrame(Evaluator& ev, const CompiledChunk& chunk, EvalCon
|
|
|
369
377
|
}
|
|
370
378
|
auto frame = ev.acquireVmFrame();
|
|
371
379
|
frame->chunk = &chunk;
|
|
372
|
-
frame->
|
|
380
|
+
frame->setCode(chunk.bodyCode);
|
|
373
381
|
frame->pc = 0;
|
|
374
382
|
frame->slots.assign(static_cast<size_t>(chunk.numSlots), Value{});
|
|
375
383
|
frame->stack.clear();
|
|
@@ -491,7 +499,7 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
491
499
|
}
|
|
492
500
|
while (ev.vmCallStack_.size() > floor) {
|
|
493
501
|
VmFrame& f = *ev.vmCallStack_.back();
|
|
494
|
-
if (f.pc >= f.
|
|
502
|
+
if (f.pc >= f.codeSize) {
|
|
495
503
|
// A module chunk produces nothing on the stack at all --
|
|
496
504
|
// its whole effect already landed in treeStack_ as a side
|
|
497
505
|
// effect of running its own body (Op::CallModule/
|
|
@@ -528,7 +536,7 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
528
536
|
continue;
|
|
529
537
|
}
|
|
530
538
|
|
|
531
|
-
const Instruction& ins =
|
|
539
|
+
const Instruction& ins = f.code[f.pc];
|
|
532
540
|
EvalContext& ctx = f.ctxChain.back();
|
|
533
541
|
switch (ins.op) {
|
|
534
542
|
case Op::PushConst:
|
|
@@ -787,27 +795,28 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
787
795
|
case Op::CallFn: {
|
|
788
796
|
const CompiledChunk::CallSite& site = f.chunk->callSites[static_cast<size_t>(ins.a)];
|
|
789
797
|
const size_t argCount = static_cast<size_t>(ins.b);
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
args[argCount - 1 - i] = std::move(f.stack.back());
|
|
793
|
-
f.stack.pop_back();
|
|
794
|
-
}
|
|
798
|
+
const size_t argBase = f.stack.size() - argCount;
|
|
799
|
+
Value* args = f.stack.data() + argBase; // into f.stack; truncated below once consumed
|
|
795
800
|
if (site.isImport) {
|
|
796
|
-
CallArgs callArgs = buildCallArgs(site, args, argCount);
|
|
801
|
+
CallArgs& callArgs = buildCallArgs(site, args, argCount, f.argScratch);
|
|
802
|
+
f.stack.resize(argBase);
|
|
797
803
|
f.stack.push_back(importAsValue(ev, callArgs, *site.callNode));
|
|
798
804
|
++f.pc;
|
|
799
805
|
} else if (site.isBuiltin && site.calleeName == "object") {
|
|
800
806
|
std::vector<std::pair<std::optional<std::string>, Value>> pairs;
|
|
801
807
|
pairs.reserve(argCount);
|
|
802
808
|
for (size_t i = 0; i < argCount; ++i) pairs.emplace_back(site.argNames[i], std::move(args[i]));
|
|
809
|
+
f.stack.resize(argBase);
|
|
803
810
|
f.stack.push_back(mergeObjectArgs(ev, pairs, &site.callNode->position()));
|
|
804
811
|
++f.pc;
|
|
805
812
|
} else if (site.isBuiltin) {
|
|
806
|
-
CallArgs callArgs = buildCallArgs(site, args, argCount);
|
|
813
|
+
CallArgs& callArgs = buildCallArgs(site, args, argCount, f.argScratch);
|
|
814
|
+
f.stack.resize(argBase);
|
|
807
815
|
f.stack.push_back(evalBuiltinFunction(ev, site.calleeName, callArgs, *site.callNode));
|
|
808
816
|
++f.pc;
|
|
809
817
|
} else {
|
|
810
818
|
BoundArgs bound = buildBoundArgs(ev, site, args, argCount, site.decl->parameters);
|
|
819
|
+
f.stack.resize(argBase);
|
|
811
820
|
const CompiledChunk* calleeChunk = ev.useBytecodeVm() ? ev.lookupOrCompileChunk(*site.decl) : nullptr;
|
|
812
821
|
if (calleeChunk) {
|
|
813
822
|
const oscad::Scope* fnScope = ctx.scopeOf(*site.decl) ? ctx.scopeOf(*site.decl) : ctx.scope;
|
|
@@ -828,17 +837,14 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
828
837
|
case Op::CallDynamic: {
|
|
829
838
|
const CompiledChunk::CallSite& site = f.chunk->callSites[static_cast<size_t>(ins.a)];
|
|
830
839
|
const size_t argCount = static_cast<size_t>(ins.b);
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
f.stack.pop_back();
|
|
835
|
-
}
|
|
836
|
-
Value callee = std::move(f.stack.back());
|
|
837
|
-
f.stack.pop_back();
|
|
840
|
+
const size_t argBase = f.stack.size() - argCount;
|
|
841
|
+
Value* args = f.stack.data() + argBase; // into f.stack; truncated below once consumed
|
|
842
|
+
Value callee = std::move(f.stack[argBase - 1]);
|
|
838
843
|
if (const auto* closurePtr = std::get_if<ClosurePtr>(&callee); closurePtr && *closurePtr) {
|
|
839
844
|
const Closure& closure = **closurePtr;
|
|
840
845
|
const oscad::FunctionLiteral& funcNode = *closure.node;
|
|
841
846
|
BoundArgs bound = buildBoundArgs(ev, site, args, argCount, funcNode.parameters);
|
|
847
|
+
f.stack.resize(argBase - 1); // also drops the callee
|
|
842
848
|
const CompiledChunk* calleeChunk = ev.useBytecodeVm() ? ev.lookupCompiledLiteralChunk(funcNode) : nullptr;
|
|
843
849
|
if (calleeChunk) {
|
|
844
850
|
const oscad::Scope* fnScope = ctx.scopeOf(funcNode) ? ctx.scopeOf(funcNode) : ctx.scope;
|
|
@@ -851,6 +857,7 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
851
857
|
}
|
|
852
858
|
} else {
|
|
853
859
|
if (!site.calleeName.empty()) ev.warn("Ignoring unknown function '" + site.calleeName + "'", ins.pos);
|
|
860
|
+
f.stack.resize(argBase - 1); // arguments and callee both go
|
|
854
861
|
f.stack.push_back(Value{});
|
|
855
862
|
++f.pc;
|
|
856
863
|
}
|
|
@@ -859,12 +866,10 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
859
866
|
case Op::CallFnTail: {
|
|
860
867
|
const CompiledChunk::CallSite& site = f.chunk->callSites[static_cast<size_t>(ins.a)];
|
|
861
868
|
const size_t argCount = static_cast<size_t>(ins.b);
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
args[argCount - 1 - i] = std::move(f.stack.back());
|
|
865
|
-
f.stack.pop_back();
|
|
866
|
-
}
|
|
869
|
+
const size_t argBase = f.stack.size() - argCount;
|
|
870
|
+
Value* args = f.stack.data() + argBase; // into f.stack; truncated below once consumed
|
|
867
871
|
BoundArgs bound = buildBoundArgs(ev, site, args, argCount, site.decl->parameters);
|
|
872
|
+
f.stack.resize(argBase);
|
|
868
873
|
// Tail-hop-in-place requires f.hopEligible -- a frame
|
|
869
874
|
// that's call-boundary-free (statement expression,
|
|
870
875
|
// assignment block, parameter default) has no
|
|
@@ -890,7 +895,7 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
890
895
|
if (calleeChunk) {
|
|
891
896
|
ev.recordTailCallHop(site.calleeName, *site.decl, &site.callNode->position(), f.tailHopGuard);
|
|
892
897
|
f.chunk = calleeChunk;
|
|
893
|
-
f.
|
|
898
|
+
f.setCode(calleeChunk->bodyCode);
|
|
894
899
|
f.pc = 0;
|
|
895
900
|
f.slots.assign(static_cast<size_t>(calleeChunk->numSlots), Value{});
|
|
896
901
|
f.stack.clear();
|
|
@@ -921,17 +926,14 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
921
926
|
case Op::CallDynamicTail: {
|
|
922
927
|
const CompiledChunk::CallSite& site = f.chunk->callSites[static_cast<size_t>(ins.a)];
|
|
923
928
|
const size_t argCount = static_cast<size_t>(ins.b);
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
f.stack.pop_back();
|
|
928
|
-
}
|
|
929
|
-
Value callee = std::move(f.stack.back());
|
|
930
|
-
f.stack.pop_back();
|
|
929
|
+
const size_t argBase = f.stack.size() - argCount;
|
|
930
|
+
Value* args = f.stack.data() + argBase; // into f.stack; truncated below once consumed
|
|
931
|
+
Value callee = std::move(f.stack[argBase - 1]);
|
|
931
932
|
if (const auto* closurePtr = std::get_if<ClosurePtr>(&callee); closurePtr && *closurePtr) {
|
|
932
933
|
const Closure& closure = **closurePtr;
|
|
933
934
|
const oscad::FunctionLiteral& funcNode = *closure.node;
|
|
934
935
|
BoundArgs bound = buildBoundArgs(ev, site, args, argCount, funcNode.parameters);
|
|
936
|
+
f.stack.resize(argBase - 1); // also drops the callee
|
|
935
937
|
const bool thisFrameBracketed = f.hopEligible;
|
|
936
938
|
std::optional<EvalContext> hopCtx = thisFrameBracketed
|
|
937
939
|
? ev.isolatedCallCtxFor(funcNode, ctx, capturedLetTrail(closure))
|
|
@@ -942,7 +944,7 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
942
944
|
if (calleeChunk) {
|
|
943
945
|
ev.recordTailCallHop("<function literal>", funcNode, ins.pos, f.tailHopGuard);
|
|
944
946
|
f.chunk = calleeChunk;
|
|
945
|
-
f.
|
|
947
|
+
f.setCode(calleeChunk->bodyCode);
|
|
946
948
|
f.pc = 0;
|
|
947
949
|
f.slots.assign(static_cast<size_t>(calleeChunk->numSlots), Value{});
|
|
948
950
|
f.stack.clear();
|
|
@@ -967,6 +969,7 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
967
969
|
}
|
|
968
970
|
} else {
|
|
969
971
|
if (!site.calleeName.empty()) ev.warn("Ignoring unknown function '" + site.calleeName + "'", ins.pos);
|
|
972
|
+
f.stack.resize(argBase - 1); // arguments and callee both go
|
|
970
973
|
f.stack.push_back(Value{});
|
|
971
974
|
++f.pc;
|
|
972
975
|
}
|
|
@@ -1559,7 +1562,7 @@ Value runCompiledFunction(Evaluator& ev, const CompiledChunk& chunk,
|
|
|
1559
1562
|
EvalContext& childCtx) {
|
|
1560
1563
|
auto frame = ev.acquireVmFrame();
|
|
1561
1564
|
frame->chunk = &chunk;
|
|
1562
|
-
frame->
|
|
1565
|
+
frame->setCode(chunk.bodyCode);
|
|
1563
1566
|
frame->pc = 0;
|
|
1564
1567
|
frame->slots.assign(static_cast<size_t>(chunk.numSlots), Value{});
|
|
1565
1568
|
frame->stack.clear();
|
|
@@ -1585,7 +1588,7 @@ Value runCompiledFunctionFromBound(Evaluator& ev, const CompiledChunk& chunk, co
|
|
|
1585
1588
|
EvalContext& childCtx) {
|
|
1586
1589
|
auto frame = ev.acquireVmFrame();
|
|
1587
1590
|
frame->chunk = &chunk;
|
|
1588
|
-
frame->
|
|
1591
|
+
frame->setCode(chunk.bodyCode);
|
|
1589
1592
|
frame->pc = 0;
|
|
1590
1593
|
frame->slots.assign(static_cast<size_t>(chunk.numSlots), Value{});
|
|
1591
1594
|
frame->stack.clear();
|
|
@@ -1644,7 +1647,7 @@ void runCompiledModuleBody(Evaluator& ev, const CompiledChunk& chunk, EvalContex
|
|
|
1644
1647
|
// exactly (VmFrame::ownsModuleSplice's own doc comment, bytecode_vm.hpp).
|
|
1645
1648
|
auto frame = ev.acquireVmFrame();
|
|
1646
1649
|
frame->chunk = &chunk;
|
|
1647
|
-
frame->
|
|
1650
|
+
frame->setCode(chunk.bodyCode);
|
|
1648
1651
|
frame->pc = 0;
|
|
1649
1652
|
// .assign, not .clear() -- a module chunk's own bodyCode has no
|
|
1650
1653
|
// PARAMETER slots (module params are always bound natively, see this
|
|
@@ -685,7 +685,7 @@ void Evaluator::recordTailCallHop(const std::string& calleeName, const oscad::AS
|
|
|
685
685
|
// here too, or it would count the OLD declaration as active forever
|
|
686
686
|
// and never see the NEW one at all.
|
|
687
687
|
noteActiveDeclExit(frame.declNode);
|
|
688
|
-
|
|
688
|
+
noteActiveDeclEnter(&calleeDecl);
|
|
689
689
|
frame.name = calleeName;
|
|
690
690
|
frame.declNode = &calleeDecl;
|
|
691
691
|
frame.declPosition = &calleeDecl.position();
|
|
@@ -736,16 +736,22 @@ Evaluator::UserCallHandle Evaluator::enterUserCall(const std::string& name, cons
|
|
|
736
736
|
callStack_.push_back(CallStackFrame{kind, name, callPos, &declNode.position(), &declNode, nullptr, upvalueParent});
|
|
737
737
|
callStack_.back().bodyCtx = &childCtx; // per-frame locals for the debugger
|
|
738
738
|
if (isModule) ++moduleCallDepth_;
|
|
739
|
-
|
|
739
|
+
noteActiveDeclEnter(&declNode);
|
|
740
740
|
if (bodyExpr) checkDebug(*bodyExpr, childCtx);
|
|
741
741
|
lastCtx_ = &childCtx;
|
|
742
742
|
return h;
|
|
743
743
|
}
|
|
744
744
|
|
|
745
745
|
void Evaluator::noteActiveDeclExit(const oscad::ASTNode* declNode) {
|
|
746
|
-
auto it = activeDeclRefcount_.
|
|
747
|
-
|
|
748
|
-
|
|
746
|
+
for (auto it = activeDeclRefcount_.begin(); it != activeDeclRefcount_.end(); ++it) {
|
|
747
|
+
if (it->first != declNode) continue;
|
|
748
|
+
if (--it->second <= 0) {
|
|
749
|
+
*it = activeDeclRefcount_.back(); // order is not meaningful
|
|
750
|
+
activeDeclRefcount_.pop_back();
|
|
751
|
+
}
|
|
752
|
+
return;
|
|
753
|
+
}
|
|
754
|
+
// not found: defensive; should always be present
|
|
749
755
|
}
|
|
750
756
|
|
|
751
757
|
void Evaluator::exitUserCallSuccess(const std::string& name, const UserCallHandle& handle, const Value& result,
|
|
@@ -17,6 +17,26 @@ size_t nextCharStart(const std::string& s, size_t i) {
|
|
|
17
17
|
|
|
18
18
|
} // namespace
|
|
19
19
|
|
|
20
|
+
std::string utf8Encode(uint32_t cp) {
|
|
21
|
+
std::string out;
|
|
22
|
+
if (cp <= 0x7F) {
|
|
23
|
+
out.push_back(static_cast<char>(cp));
|
|
24
|
+
} else if (cp <= 0x7FF) {
|
|
25
|
+
out.push_back(static_cast<char>(0xC0 | (cp >> 6)));
|
|
26
|
+
out.push_back(static_cast<char>(0x80 | (cp & 0x3F)));
|
|
27
|
+
} else if (cp <= 0xFFFF) {
|
|
28
|
+
out.push_back(static_cast<char>(0xE0 | (cp >> 12)));
|
|
29
|
+
out.push_back(static_cast<char>(0x80 | ((cp >> 6) & 0x3F)));
|
|
30
|
+
out.push_back(static_cast<char>(0x80 | (cp & 0x3F)));
|
|
31
|
+
} else {
|
|
32
|
+
out.push_back(static_cast<char>(0xF0 | (cp >> 18)));
|
|
33
|
+
out.push_back(static_cast<char>(0x80 | ((cp >> 12) & 0x3F)));
|
|
34
|
+
out.push_back(static_cast<char>(0x80 | ((cp >> 6) & 0x3F)));
|
|
35
|
+
out.push_back(static_cast<char>(0x80 | (cp & 0x3F)));
|
|
36
|
+
}
|
|
37
|
+
return out;
|
|
38
|
+
}
|
|
39
|
+
|
|
20
40
|
bool utf8IsAscii(const std::string& s) {
|
|
21
41
|
for (char c : s) {
|
|
22
42
|
if (static_cast<unsigned char>(c) >= 0x80) return false;
|