openscad-cpp-evaluator 1.6.1__tar.gz → 1.7.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.6.1 → openscad_cpp_evaluator-1.7.0}/PKG-INFO +1 -1
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/bytecode.hpp +35 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/function_builtins.hpp +27 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/pyproject.toml +1 -1
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/builtins/function_builtins.cpp +16 -12
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/bytecode_compiler.cpp +48 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/bytecode_vm.cpp +123 -22
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/mesh_check.cpp +92 -19
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_bytecode_compiler.cpp +65 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_mesh_check.cpp +13 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/.github/workflows/wheels.yml +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/.gitignore +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/.gitmodules +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/LICENSE +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/README.md +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/bindings/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/bindings/ast_to_py.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/bindings/module.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/cmake/embed_font.cmake +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/examples/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/examples/eval_perf_benchmark.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/examples/manifold_cache_reuse.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/examples/minimal_debugger.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/.gitignore +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/README.md +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope_table.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/src/api.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/src/comments.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/src/position.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/src/scope.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/tests/test_render_expression.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/bytecode_vm.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/colored_body.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/evaluator.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/export.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/font_match.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/format_closure.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/freetype_font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/mesh_check.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/profile.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/scope_trail.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/segments.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/utf8.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/value.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/python/openscad_cpp_evaluator/__init__.py +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/resources/fonts/LICENSE +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/resources/fonts/LiberationSans-Regular.ttf +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/builtins/booleans.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/builtins/builtins.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/builtins/call_args.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/builtins/color.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/builtins/control.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/builtins/dxf_dim.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/builtins/extrude.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/builtins/import.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/builtins/modifiers.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/builtins/primitives_2d.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/builtins/primitives_3d.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/builtins/registry.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/builtins/roof.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/builtins/segments.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/builtins/surface.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/builtins/text.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/builtins/topology.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/builtins/transforms.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/colored_body.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/csg_generate.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/csg_resolve.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/css_colors.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/debug/debug_repl.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/debug_profile.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/eval_context.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/eval_error.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/eval_use.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/export.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/format_closure.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/import/dxf_import.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/import/mesh_import.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/import/surface_load.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/import/svg_import.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/measure_geometry.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/stmt_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/text/font_match.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/text/freetype_font_provider.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/text/text_metrics.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/user_calls.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/utf8.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/value.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_booleans.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_children_separate.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_cli.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_control_flow.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_csg_tree.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_debug_hooks.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_dxf_svg_import.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_eval_context.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_export.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_extrude_roof.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_feature_detection.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_import_export.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_include_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_multi_color_merge.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_primitives.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_profiling.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_python_bindings.py +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_render_expr.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_scope_trail.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_scoping.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_surface.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_tail_calls.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_text.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_transforms.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_unexpected_args.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_use.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_value.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_viewport_params.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tests/test_zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tools/cli/cli_lib.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tools/cli/cli_lib.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/uv.lock +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
+
#include "openscad_cpp_evaluator/function_builtins.hpp"
|
|
3
4
|
#include "openscad_cpp_evaluator/value.hpp"
|
|
4
5
|
|
|
5
6
|
#include "openscad_cpp_parser/ast/ast_node.hpp"
|
|
@@ -787,6 +788,40 @@ struct CompiledChunk {
|
|
|
787
788
|
const oscad::FunctionDeclaration* decl = nullptr;
|
|
788
789
|
std::vector<std::optional<std::string>> argNames;
|
|
789
790
|
const oscad::ASTNode* callNode = nullptr;
|
|
791
|
+
// Everything below is `calleeName` already looked up, once, here at
|
|
792
|
+
// compile time. The VM used to redo all three on EVERY builtin call:
|
|
793
|
+
// two std::string hashes into static tables plus a string compare
|
|
794
|
+
// against "object", for answers that cannot change once this site is
|
|
795
|
+
// compiled. `declaredParams` points into a function-local static
|
|
796
|
+
// table with process lifetime, so holding the pointer is safe.
|
|
797
|
+
BuiltinFnId builtinId = BuiltinFnId::None;
|
|
798
|
+
const std::vector<std::string>* declaredParams = nullptr;
|
|
799
|
+
bool isObjectBuiltin = false;
|
|
800
|
+
|
|
801
|
+
// Where each argument of this call goes, worked out once at compile
|
|
802
|
+
// time against `decl`'s parameter list -- see ArgBind. Only filled in
|
|
803
|
+
// for a static user-function callee (`decl` set); a builtin, an
|
|
804
|
+
// import or a dynamic/closure callee has no compile-time parameter
|
|
805
|
+
// list to match against and keeps the name-matching path.
|
|
806
|
+
//
|
|
807
|
+
// The names on both sides of that matching are fixed the moment this
|
|
808
|
+
// site is compiled, but the VM was redoing it on every call, twice:
|
|
809
|
+
// buildBoundArgs linear-scanned a name-keyed BoundArgs (copying each
|
|
810
|
+
// name into it), then bindBoundArgsIntoFrame linear-scanned it again
|
|
811
|
+
// for every parameter, then a third nested loop compared every bound
|
|
812
|
+
// name against every parameter name. A two-argument call did roughly
|
|
813
|
+
// ten std::string comparisons and two string copies to reach an
|
|
814
|
+
// answer that was already known. Binding straight into the frame's
|
|
815
|
+
// slots also MOVES each argument instead of moving it into BoundArgs
|
|
816
|
+
// and copying it back out.
|
|
817
|
+
struct ArgBind {
|
|
818
|
+
int paramIndex = -1; // >=0: this argument binds that parameter
|
|
819
|
+
bool toDyn = false; // instead bind by name into ctx.dyn ($-named, undeclared)
|
|
820
|
+
bool warnUnexpectedNamed = false;
|
|
821
|
+
bool warnTooManyPositional = false;
|
|
822
|
+
};
|
|
823
|
+
std::vector<ArgBind> argBinds;
|
|
824
|
+
bool hasArgPlan = false; // argBinds is authoritative (it is empty for a zero-argument call too)
|
|
790
825
|
};
|
|
791
826
|
|
|
792
827
|
// An upvalue read (see Op::LoadUpvalue): `targetDecl` is the enclosing
|
|
@@ -26,8 +26,35 @@ bool isBuiltinFunctionName(const std::string& name);
|
|
|
26
26
|
// accept $-prefixed named-argument overrides). Mirrors the reference's
|
|
27
27
|
// _math_fns dispatch table plus the textmetrics()/fontmetrics() special
|
|
28
28
|
// cases (implemented on top of FontProvider, text_metrics.hpp).
|
|
29
|
+
// One id per name evalBuiltinFunction handles (NOT the same list as
|
|
30
|
+
// isBuiltinFunctionName -- "object" is deliberately absent, since it is
|
|
31
|
+
// special-cased to builtinObject() before this function is reached). Public
|
|
32
|
+
// so a CALL SITE can resolve its callee once, at compile time
|
|
33
|
+
// (CompiledChunk::CallSite::builtinId), instead of hashing the name string
|
|
34
|
+
// on every single call.
|
|
35
|
+
enum class BuiltinFnId {
|
|
36
|
+
None, // not a name evalBuiltinFunction handles
|
|
37
|
+
TextMetrics, FontMetrics, Abs, Sign, Ceil, Floor, Round, Sqrt, Ln, Log, Exp, Sin, Cos, Tan,
|
|
38
|
+
Asin, Acos, Atan, Atan2, Max, Min, Pow, Norm, Cross, Rands, Concat, Len, Str, Chr, Ord,
|
|
39
|
+
IsUndef, IsNum, IsBool, IsString, IsList, IsFunction, IsObject, Search, Lookup, HasKey,
|
|
40
|
+
Version, VersionNum, ParentModule, DxfDim, DxfCross, SupportedFeature, LinearSolve,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// `name` -> its id, or None. The one place that hashes the name; everything
|
|
44
|
+
// on a hot path should call this once at compile time and keep the answer.
|
|
45
|
+
BuiltinFnId builtinFnIdFor(const std::string& name);
|
|
46
|
+
|
|
29
47
|
Value evalBuiltinFunction(Evaluator& ev, const std::string& name, const CallArgs& args, const oscad::ASTNode& node);
|
|
30
48
|
|
|
49
|
+
// The same dispatch with both of its name lookups already done: `id` from
|
|
50
|
+
// builtinFnIdFor and `declaredParams` from builtinParamNames (dispatch.hpp),
|
|
51
|
+
// which for all but a couple of builtins is null. `name` survives only
|
|
52
|
+
// because diagnostics quote it. The string-taking overload above is just
|
|
53
|
+
// this one with the two lookups performed first, and remains the entry point
|
|
54
|
+
// for the AST interpreter, where there is no call site to cache them on.
|
|
55
|
+
Value evalBuiltinFunctionResolved(Evaluator& ev, BuiltinFnId id, const std::vector<std::string>* declaredParams,
|
|
56
|
+
const std::string& name, const CallArgs& args, const oscad::ASTNode& node);
|
|
57
|
+
|
|
31
58
|
// object(a=1, b=2, ...) -- an ordered string-keyed map merging positional
|
|
32
59
|
// (an existing object's entries, or a list of [key,value] pairs) and named
|
|
33
60
|
// arguments, later arguments winning over earlier ones for the same key --
|
{openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.0}/src/builtins/function_builtins.cpp
RENAMED
|
@@ -1007,12 +1007,7 @@ namespace {
|
|
|
1007
1007
|
// `if (name == "...")` string-compare chain; the switch below then
|
|
1008
1008
|
// compiles to a jump table instead of sequential comparisons. No branch's
|
|
1009
1009
|
// logic changed, only how it's reached.
|
|
1010
|
-
|
|
1011
|
-
TextMetrics, FontMetrics, Abs, Sign, Ceil, Floor, Round, Sqrt, Ln, Log, Exp, Sin, Cos, Tan,
|
|
1012
|
-
Asin, Acos, Atan, Atan2, Max, Min, Pow, Norm, Cross, Rands, Concat, Len, Str, Chr, Ord,
|
|
1013
|
-
IsUndef, IsNum, IsBool, IsString, IsList, IsFunction, IsObject, Search, Lookup, HasKey,
|
|
1014
|
-
Version, VersionNum, ParentModule, DxfDim, DxfCross, SupportedFeature, LinearSolve,
|
|
1015
|
-
};
|
|
1010
|
+
// BuiltinFnId itself now lives in function_builtins.hpp -- see builtinFnIdFor.
|
|
1016
1011
|
|
|
1017
1012
|
// supported_feature("name") -> the level at which this build implements that
|
|
1018
1013
|
// feature, or 0 for one it does not implement (and for a name it has never
|
|
@@ -1242,18 +1237,26 @@ bool checkBuiltinArgs(Evaluator& ev, const std::string& name, BuiltinFnId id, co
|
|
|
1242
1237
|
|
|
1243
1238
|
} // namespace
|
|
1244
1239
|
|
|
1240
|
+
BuiltinFnId builtinFnIdFor(const std::string& name) {
|
|
1241
|
+
const auto& ids = builtinFnIds();
|
|
1242
|
+
const auto it = ids.find(name);
|
|
1243
|
+
return it == ids.end() ? BuiltinFnId::None : it->second;
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1245
1246
|
Value evalBuiltinFunction(Evaluator& ev, const std::string& name, const CallArgs& args, const oscad::ASTNode& node) {
|
|
1247
|
+
return evalBuiltinFunctionResolved(ev, builtinFnIdFor(name), builtinParamNames(name), name, args, node);
|
|
1248
|
+
}
|
|
1246
1249
|
|
|
1247
|
-
|
|
1248
|
-
|
|
1250
|
+
Value evalBuiltinFunctionResolved(Evaluator& ev, BuiltinFnId id, const std::vector<std::string>* declaredParams,
|
|
1251
|
+
const std::string& name, const CallArgs& args, const oscad::ASTNode& node) {
|
|
1249
1252
|
// Not one of the names this function handles (e.g. "object", routed
|
|
1250
1253
|
// elsewhere before reaching here) -- mirrors the old chain's fallthrough.
|
|
1251
|
-
if (
|
|
1254
|
+
if (id == BuiltinFnId::None) return Value{};
|
|
1252
1255
|
|
|
1253
1256
|
// Only textmetrics/fontmetrics have an entry -- every other builtin
|
|
1254
1257
|
// function reads its arguments positionally upstream and warns about
|
|
1255
1258
|
// nothing. See builtinParamNames (registry.cpp).
|
|
1256
|
-
if (const std::vector<std::string>* declared =
|
|
1259
|
+
if (const std::vector<std::string>* declared = declaredParams) {
|
|
1257
1260
|
for (const auto& [argName, _] : args.named) {
|
|
1258
1261
|
if (!isConfigVariable(argName) &&
|
|
1259
1262
|
std::find(declared->begin(), declared->end(), argName) == declared->end()) {
|
|
@@ -1265,9 +1268,10 @@ Value evalBuiltinFunction(Evaluator& ev, const std::string& name, const CallArgs
|
|
|
1265
1268
|
// Arity and argument types, with the reference's own two diagnostics.
|
|
1266
1269
|
// This replaced a silent version of the same gate (scalarNumericArity /
|
|
1267
1270
|
// numericOnlyNames), which returned undef without ever saying why.
|
|
1268
|
-
if (!checkBuiltinArgs(ev, name,
|
|
1271
|
+
if (!checkBuiltinArgs(ev, name, id, args, &node.position())) return Value{};
|
|
1269
1272
|
|
|
1270
|
-
switch (
|
|
1273
|
+
switch (id) {
|
|
1274
|
+
case BuiltinFnId::None: return Value{}; // unreachable: handled above
|
|
1271
1275
|
case BuiltinFnId::TextMetrics: return builtinTextmetrics(ev, args);
|
|
1272
1276
|
case BuiltinFnId::FontMetrics: return builtinFontmetrics(ev, args);
|
|
1273
1277
|
case BuiltinFnId::Abs: return Value{std::fabs(toDoubleLenient(getArg(args, 0, "x", Value{})))};
|
|
@@ -20,6 +20,46 @@
|
|
|
20
20
|
namespace oscadeval {
|
|
21
21
|
|
|
22
22
|
namespace {
|
|
23
|
+
// Replays buildBoundArgs' own positional/named matching rule (bytecode_vm.cpp)
|
|
24
|
+
// against a parameter list known at compile time, recording the answer per
|
|
25
|
+
// argument instead of recomputing it per call. The rule, unchanged: a named
|
|
26
|
+
// argument binds the parameter of that name, warning when there is none and
|
|
27
|
+
// the name is not a $-config variable; a positional argument binds the
|
|
28
|
+
// parameter at its own positional index, warning once when it runs past the
|
|
29
|
+
// end; an undeclared $-name still reaches ctx.dyn; anything else is dropped.
|
|
30
|
+
// A later argument writing the same parameter still wins, because both bind
|
|
31
|
+
// the same slot in order.
|
|
32
|
+
void planCallSiteArgs(CompiledChunk::CallSite& site,
|
|
33
|
+
const std::vector<std::unique_ptr<oscad::ParameterDeclaration>>& params) {
|
|
34
|
+
const size_t nparams = params.size();
|
|
35
|
+
size_t positionalIdx = 0;
|
|
36
|
+
site.argBinds.resize(site.argNames.size());
|
|
37
|
+
for (size_t i = 0; i < site.argNames.size(); ++i) {
|
|
38
|
+
CompiledChunk::CallSite::ArgBind& b = site.argBinds[i];
|
|
39
|
+
if (site.argNames[i]) {
|
|
40
|
+
const std::string& name = *site.argNames[i];
|
|
41
|
+
int found = -1;
|
|
42
|
+
for (size_t p = 0; p < nparams; ++p) {
|
|
43
|
+
if (params[p]->name->name == name) {
|
|
44
|
+
found = static_cast<int>(p);
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
b.paramIndex = found;
|
|
49
|
+
b.warnUnexpectedNamed = (found < 0) && !isConfigVariable(name);
|
|
50
|
+
b.toDyn = (found < 0) && !name.empty() && name[0] == '$';
|
|
51
|
+
} else {
|
|
52
|
+
if (positionalIdx < nparams) {
|
|
53
|
+
b.paramIndex = static_cast<int>(positionalIdx);
|
|
54
|
+
} else if (positionalIdx == nparams) {
|
|
55
|
+
b.warnTooManyPositional = true;
|
|
56
|
+
}
|
|
57
|
+
++positionalIdx;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
site.hasArgPlan = true;
|
|
61
|
+
}
|
|
62
|
+
|
|
23
63
|
|
|
24
64
|
// Thrown by compileExpr wherever it hits a construct this phase doesn't
|
|
25
65
|
// compile yet -- tryCompileFunction catches it and returns nullopt (falls
|
|
@@ -601,6 +641,11 @@ public:
|
|
|
601
641
|
// call-site interleaved order, not resolveArgs'
|
|
602
642
|
// split positional/named CallArgs shape).
|
|
603
643
|
site.isBuiltin = true;
|
|
644
|
+
// Resolve the callee here rather than per call; see
|
|
645
|
+
// CallSite's own doc comment (bytecode.hpp).
|
|
646
|
+
site.builtinId = builtinFnIdFor(calleeName);
|
|
647
|
+
site.declaredParams = builtinParamNames(calleeName);
|
|
648
|
+
site.isObjectBuiltin = (calleeName == "object");
|
|
604
649
|
isStatic = true;
|
|
605
650
|
}
|
|
606
651
|
// Anything else stays dynamic: a function-literal value,
|
|
@@ -674,6 +719,9 @@ public:
|
|
|
674
719
|
}
|
|
675
720
|
}
|
|
676
721
|
}
|
|
722
|
+
// Resolve every argument to its parameter now; see
|
|
723
|
+
// CallSite::argBinds (bytecode.hpp) for why.
|
|
724
|
+
if (site.decl) planCallSiteArgs(site, site.decl->parameters);
|
|
677
725
|
int siteIdx = static_cast<int>(chunk_.callSites.size());
|
|
678
726
|
chunk_.callSites.push_back(std::move(site));
|
|
679
727
|
// Builtins and import() never trampoline (matching
|
|
@@ -49,8 +49,12 @@ CallArgs& buildCallArgs(const CompiledChunk::CallSite& site, Value* args, size_t
|
|
|
49
49
|
// LIST is `paramNames` (in declared order -- a FunctionDeclaration's
|
|
50
50
|
// parameters or a FunctionLiteral's). Shared by CallFn/CallFnTail (a
|
|
51
51
|
// site.decl callee) and CallDynamic/CallDynamicTail (a closure callee).
|
|
52
|
+
// `emitWarnings=false` is for the one caller that has already emitted them
|
|
53
|
+
// through warnPlannedArgs and only needs the binding -- see Op::CallFnTail's
|
|
54
|
+
// no-hop fallback.
|
|
52
55
|
BoundArgs buildBoundArgs(Evaluator& ev, const CompiledChunk::CallSite& site, Value* args, size_t argCount,
|
|
53
|
-
const std::vector<std::unique_ptr<oscad::ParameterDeclaration>>& paramNames
|
|
56
|
+
const std::vector<std::unique_ptr<oscad::ParameterDeclaration>>& paramNames,
|
|
57
|
+
bool emitWarnings = true) {
|
|
54
58
|
BoundArgs bound;
|
|
55
59
|
bound.reserve(argCount);
|
|
56
60
|
size_t positionalIdx = 0;
|
|
@@ -59,14 +63,14 @@ BoundArgs buildBoundArgs(Evaluator& ev, const CompiledChunk::CallSite& site, Val
|
|
|
59
63
|
for (size_t i = 0; i < argCount; ++i) {
|
|
60
64
|
if (site.argNames[i]) {
|
|
61
65
|
const std::string& name = *site.argNames[i];
|
|
62
|
-
if (!isConfigVariable(name) && !declaresParam(paramNames, name)) {
|
|
66
|
+
if (emitWarnings && !isConfigVariable(name) && !declaresParam(paramNames, name)) {
|
|
63
67
|
warnUnexpectedNamedArg(ev, name, pos);
|
|
64
68
|
}
|
|
65
69
|
bound.set(name, std::move(args[i]));
|
|
66
70
|
} else {
|
|
67
71
|
if (positionalIdx < nparams) {
|
|
68
72
|
bound.set(paramNames[positionalIdx]->name->name, std::move(args[i]));
|
|
69
|
-
} else if (positionalIdx == nparams) {
|
|
73
|
+
} else if (emitWarnings && positionalIdx == nparams) {
|
|
70
74
|
warnTooManyPositionalArgs(ev, pos);
|
|
71
75
|
}
|
|
72
76
|
++positionalIdx;
|
|
@@ -108,6 +112,60 @@ void bindBoundArgsIntoFrame(const CompiledChunk& chunk, const BoundArgs& bound,
|
|
|
108
112
|
}
|
|
109
113
|
}
|
|
110
114
|
|
|
115
|
+
// Where a pushed frame's arguments come from: a call site's compile-time plan
|
|
116
|
+
// over the caller's own live operand stack (the hot path), or an
|
|
117
|
+
// already-name-matched BoundArgs (closures and dynamic callees, which have no
|
|
118
|
+
// compile-time parameter list to plan against).
|
|
119
|
+
struct FrameArgs {
|
|
120
|
+
const CompiledChunk::CallSite* site = nullptr;
|
|
121
|
+
Value* args = nullptr;
|
|
122
|
+
size_t argCount = 0;
|
|
123
|
+
const BoundArgs* bound = nullptr;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
// The compile-time counterpart of bindBoundArgsIntoFrame: binds a call's
|
|
127
|
+
// arguments straight from the caller's operand stack into the callee frame,
|
|
128
|
+
// using the plan its call site worked out once (CallSite::argBinds). No name
|
|
129
|
+
// is compared and no BoundArgs is built, and each argument is MOVED into its
|
|
130
|
+
// slot rather than moved into a BoundArgs and copied back out. `args` must
|
|
131
|
+
// still be live -- the caller truncates its stack only after this returns.
|
|
132
|
+
// The argument diagnostics of a planned call, split out of the binder below
|
|
133
|
+
// because WHEN they fire is observable: their "TRACE: called by ..." line
|
|
134
|
+
// names whatever is on top of the call stack, and a tail hop has already
|
|
135
|
+
// replaced that with the CALLEE by the time it binds. buildBoundArgs warned
|
|
136
|
+
// before any of that happened, so this must too -- caught by
|
|
137
|
+
// UnexpectedArgs.NestedUserFunctionCallStillWarns, which compares the VM
|
|
138
|
+
// against the interpreter.
|
|
139
|
+
void warnPlannedArgs(Evaluator& ev, const CompiledChunk::CallSite& site, size_t argCount) {
|
|
140
|
+
const oscad::Position* pos = site.callNode ? &site.callNode->position() : nullptr;
|
|
141
|
+
for (size_t i = 0; i < argCount; ++i) {
|
|
142
|
+
const CompiledChunk::CallSite::ArgBind& b = site.argBinds[i];
|
|
143
|
+
if (b.warnUnexpectedNamed) warnUnexpectedNamedArg(ev, *site.argNames[i], pos);
|
|
144
|
+
if (b.warnTooManyPositional) warnTooManyPositionalArgs(ev, pos);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
void bindPlannedArgsIntoFrame(const CompiledChunk& chunk, const CompiledChunk::CallSite& site, Value* args,
|
|
149
|
+
size_t argCount, VmFrame& frame) {
|
|
150
|
+
EvalContext& ctx = frame.ctxChain.back();
|
|
151
|
+
for (size_t i = 0; i < argCount; ++i) {
|
|
152
|
+
const CompiledChunk::CallSite::ArgBind& b = site.argBinds[i];
|
|
153
|
+
if (b.paramIndex >= 0) {
|
|
154
|
+
const CompiledChunk::Param& p = chunk.params[static_cast<size_t>(b.paramIndex)];
|
|
155
|
+
if (p.isDyn) {
|
|
156
|
+
ctx.dyn->set(p.name, std::move(args[i]));
|
|
157
|
+
} else {
|
|
158
|
+
frame.slots[static_cast<size_t>(p.slot)] = std::move(args[i]);
|
|
159
|
+
}
|
|
160
|
+
frame.bound[static_cast<size_t>(b.paramIndex)] = true;
|
|
161
|
+
} else if (b.toDyn) {
|
|
162
|
+
ctx.dyn->set(*site.argNames[i], std::move(args[i]));
|
|
163
|
+
}
|
|
164
|
+
// else: an undeclared plain name, or a positional past the end --
|
|
165
|
+
// dropped, exactly as the name-matching path drops it.
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
111
169
|
// Same, but for a call site whose arguments are still raw AST (evaluated
|
|
112
170
|
// here against `callerCtx`) -- only ever used by runCompiledFunction's own
|
|
113
171
|
// entry point (a top-level call with raw AST arguments, mirroring
|
|
@@ -249,7 +307,7 @@ void pushBareFrame(Evaluator& ev, const CompiledChunk& chunk, const std::vector<
|
|
|
249
307
|
// own parameters exactly (a FunctionDeclaration's decl/*decl.expr, or a
|
|
250
308
|
// FunctionLiteral's funcNode/*funcNode.body).
|
|
251
309
|
void pushBracketedCallFrame(Evaluator& ev, const CompiledChunk& chunk, const oscad::ASTNode& declNode,
|
|
252
|
-
const oscad::Expression& bodyExpr, const std::string& name,
|
|
310
|
+
const oscad::Expression& bodyExpr, const std::string& name, const FrameArgs& fargs,
|
|
253
311
|
EvalContext& callerCtx, const oscad::Scope* fnScope,
|
|
254
312
|
const std::shared_ptr<TrailView<Value>>& capturedLet, const oscad::Position* callPos) {
|
|
255
313
|
if (ev.vmCallStack_.size() >= Evaluator::kMaxVmCallStackDepth) {
|
|
@@ -274,7 +332,11 @@ void pushBracketedCallFrame(Evaluator& ev, const CompiledChunk& chunk, const osc
|
|
|
274
332
|
frame->tailHopGuard = 0;
|
|
275
333
|
frame->logicalName = name;
|
|
276
334
|
frame->hopEligible = true; // just pushed a fresh, correctly-named callStack_ entry
|
|
277
|
-
|
|
335
|
+
if (fargs.site) {
|
|
336
|
+
bindPlannedArgsIntoFrame(chunk, *fargs.site, fargs.args, fargs.argCount, *frame);
|
|
337
|
+
} else {
|
|
338
|
+
bindBoundArgsIntoFrame(chunk, *fargs.bound, *frame);
|
|
339
|
+
}
|
|
278
340
|
applyCompiledDefaultsToFrame(ev, chunk, *frame);
|
|
279
341
|
|
|
280
342
|
// enterUserCall's own bodyCtx must point at frame->ctxChain's OWN
|
|
@@ -802,7 +864,7 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
802
864
|
f.stack.resize(argBase);
|
|
803
865
|
f.stack.push_back(importAsValue(ev, callArgs, *site.callNode));
|
|
804
866
|
++f.pc;
|
|
805
|
-
} else if (site.
|
|
867
|
+
} else if (site.isObjectBuiltin) {
|
|
806
868
|
std::vector<std::pair<std::optional<std::string>, Value>> pairs;
|
|
807
869
|
pairs.reserve(argCount);
|
|
808
870
|
for (size_t i = 0; i < argCount; ++i) pairs.emplace_back(site.argNames[i], std::move(args[i]));
|
|
@@ -812,24 +874,39 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
812
874
|
} else if (site.isBuiltin) {
|
|
813
875
|
CallArgs& callArgs = buildCallArgs(site, args, argCount, f.argScratch);
|
|
814
876
|
f.stack.resize(argBase);
|
|
815
|
-
f.stack.push_back(
|
|
877
|
+
f.stack.push_back(evalBuiltinFunctionResolved(ev, site.builtinId, site.declaredParams,
|
|
878
|
+
site.calleeName, callArgs, *site.callNode));
|
|
816
879
|
++f.pc;
|
|
817
880
|
} else {
|
|
818
|
-
BoundArgs bound = buildBoundArgs(ev, site, args, argCount, site.decl->parameters);
|
|
819
|
-
f.stack.resize(argBase);
|
|
820
881
|
const CompiledChunk* calleeChunk = ev.useBytecodeVm() ? ev.lookupOrCompileChunk(*site.decl) : nullptr;
|
|
821
|
-
if (calleeChunk) {
|
|
882
|
+
if (calleeChunk && site.hasArgPlan) {
|
|
883
|
+
warnPlannedArgs(ev, site, argCount);
|
|
884
|
+
// The hot path: bind straight off this frame's own
|
|
885
|
+
// stack using the site's compile-time plan, then
|
|
886
|
+
// truncate. Truncating FIRST would destroy the very
|
|
887
|
+
// values being bound.
|
|
822
888
|
const oscad::Scope* fnScope = ctx.scopeOf(*site.decl) ? ctx.scopeOf(*site.decl) : ctx.scope;
|
|
823
889
|
pushBracketedCallFrame(ev, *calleeChunk, *site.decl, *site.decl->expr, site.calleeName,
|
|
824
|
-
|
|
890
|
+
FrameArgs{&site, args, argCount, nullptr}, ctx, fnScope, nullptr,
|
|
891
|
+
&site.callNode->position());
|
|
892
|
+
f.stack.resize(argBase);
|
|
825
893
|
// f.pc deliberately NOT advanced -- resumes when the
|
|
826
894
|
// pushed frame completes (see driveVm's own
|
|
827
895
|
// completion branch, above).
|
|
828
896
|
} else {
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
897
|
+
BoundArgs bound = buildBoundArgs(ev, site, args, argCount, site.decl->parameters);
|
|
898
|
+
f.stack.resize(argBase);
|
|
899
|
+
if (calleeChunk) {
|
|
900
|
+
const oscad::Scope* fnScope = ctx.scopeOf(*site.decl) ? ctx.scopeOf(*site.decl) : ctx.scope;
|
|
901
|
+
pushBracketedCallFrame(ev, *calleeChunk, *site.decl, *site.decl->expr, site.calleeName,
|
|
902
|
+
FrameArgs{nullptr, nullptr, 0, &bound}, ctx, fnScope, nullptr,
|
|
903
|
+
&site.callNode->position());
|
|
904
|
+
} else {
|
|
905
|
+
Value result = ev.evalUserFunctionFromBound(site.calleeName, *site.decl, std::move(bound),
|
|
906
|
+
ctx, &site.callNode->position());
|
|
907
|
+
f.stack.push_back(std::move(result));
|
|
908
|
+
++f.pc;
|
|
909
|
+
}
|
|
833
910
|
}
|
|
834
911
|
}
|
|
835
912
|
break;
|
|
@@ -849,7 +926,7 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
849
926
|
if (calleeChunk) {
|
|
850
927
|
const oscad::Scope* fnScope = ctx.scopeOf(funcNode) ? ctx.scopeOf(funcNode) : ctx.scope;
|
|
851
928
|
pushBracketedCallFrame(ev, *calleeChunk, funcNode, *funcNode.body, "<function literal>",
|
|
852
|
-
|
|
929
|
+
FrameArgs{nullptr, nullptr, 0, &bound}, ctx, fnScope, capturedLetTrail(closure), ins.pos);
|
|
853
930
|
} else {
|
|
854
931
|
Value result = ev.evalFunctionLiteralFromBound(closure, std::move(bound), ctx, ins.pos);
|
|
855
932
|
f.stack.push_back(std::move(result));
|
|
@@ -868,8 +945,17 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
868
945
|
const size_t argCount = static_cast<size_t>(ins.b);
|
|
869
946
|
const size_t argBase = f.stack.size() - argCount;
|
|
870
947
|
Value* args = f.stack.data() + argBase; // into f.stack; truncated below once consumed
|
|
871
|
-
|
|
872
|
-
|
|
948
|
+
// A planned site defers both of these: the arguments have
|
|
949
|
+
// to stay live on this frame's own stack until they are
|
|
950
|
+
// bound, and a tail HOP binds into this very frame.
|
|
951
|
+
const bool planned = site.hasArgPlan;
|
|
952
|
+
BoundArgs bound;
|
|
953
|
+
if (planned) {
|
|
954
|
+
warnPlannedArgs(ev, site, argCount); // before recordTailCallHop; see warnPlannedArgs
|
|
955
|
+
} else {
|
|
956
|
+
bound = buildBoundArgs(ev, site, args, argCount, site.decl->parameters);
|
|
957
|
+
f.stack.resize(argBase);
|
|
958
|
+
}
|
|
873
959
|
// Tail-hop-in-place requires f.hopEligible -- a frame
|
|
874
960
|
// that's call-boundary-free (statement expression,
|
|
875
961
|
// assignment block, parameter default) has no
|
|
@@ -898,22 +984,37 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
898
984
|
f.setCode(calleeChunk->bodyCode);
|
|
899
985
|
f.pc = 0;
|
|
900
986
|
f.slots.assign(static_cast<size_t>(calleeChunk->numSlots), Value{});
|
|
901
|
-
f.stack.clear();
|
|
902
987
|
f.bound.assign(calleeChunk->params.size(), false);
|
|
903
988
|
f.accumStack.clear();
|
|
904
989
|
f.iterLists.assign(static_cast<size_t>(calleeChunk->numIterLists), IterList{});
|
|
905
990
|
f.ctxChain.push_back(std::move(*hopCtx));
|
|
906
|
-
|
|
991
|
+
// The stack is cleared AFTER binding on the planned
|
|
992
|
+
// path: a hop rebinds this same frame, and `args`
|
|
993
|
+
// still points into the stack it would have wiped.
|
|
994
|
+
if (planned) {
|
|
995
|
+
bindPlannedArgsIntoFrame(*calleeChunk, site, args, argCount, f);
|
|
996
|
+
f.stack.clear();
|
|
997
|
+
} else {
|
|
998
|
+
f.stack.clear();
|
|
999
|
+
bindBoundArgsIntoFrame(*calleeChunk, bound, f);
|
|
1000
|
+
}
|
|
907
1001
|
applyCompiledDefaultsToFrame(ev, *calleeChunk, f);
|
|
908
1002
|
// continue via the outer while -- re-fetches this
|
|
909
1003
|
// same (now-mutated) frame from its new pc=0.
|
|
910
1004
|
} else {
|
|
1005
|
+
if (planned) { // no hop after all -- fall back to name matching
|
|
1006
|
+
// warnPlannedArgs already emitted these above.
|
|
1007
|
+
bound = buildBoundArgs(ev, site, args, argCount, site.decl->parameters,
|
|
1008
|
+
/*emitWarnings=*/false);
|
|
1009
|
+
f.stack.resize(argBase);
|
|
1010
|
+
}
|
|
911
1011
|
const CompiledChunk* fallbackChunk =
|
|
912
1012
|
ev.useBytecodeVm() ? ev.lookupOrCompileChunk(*site.decl) : nullptr;
|
|
913
1013
|
if (fallbackChunk) {
|
|
914
1014
|
const oscad::Scope* fnScope = ctx.scopeOf(*site.decl) ? ctx.scopeOf(*site.decl) : ctx.scope;
|
|
915
1015
|
pushBracketedCallFrame(ev, *fallbackChunk, *site.decl, *site.decl->expr, site.calleeName,
|
|
916
|
-
|
|
1016
|
+
FrameArgs{nullptr, nullptr, 0, &bound}, ctx, fnScope, nullptr,
|
|
1017
|
+
&site.callNode->position());
|
|
917
1018
|
} else {
|
|
918
1019
|
Value result = ev.evalUserFunctionFromBound(site.calleeName, *site.decl, std::move(bound), ctx,
|
|
919
1020
|
&site.callNode->position());
|
|
@@ -960,7 +1061,7 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
960
1061
|
if (fallbackChunk) {
|
|
961
1062
|
const oscad::Scope* fnScope = ctx.scopeOf(funcNode) ? ctx.scopeOf(funcNode) : ctx.scope;
|
|
962
1063
|
pushBracketedCallFrame(ev, *fallbackChunk, funcNode, *funcNode.body, "<function literal>",
|
|
963
|
-
|
|
1064
|
+
FrameArgs{nullptr, nullptr, 0, &bound}, ctx, fnScope, capturedLetTrail(closure), ins.pos);
|
|
964
1065
|
} else {
|
|
965
1066
|
Value result = ev.evalFunctionLiteralFromBound(closure, std::move(bound), ctx, ins.pos);
|
|
966
1067
|
f.stack.push_back(std::move(result));
|