openscad-cpp-evaluator 1.6.1__tar.gz → 1.7.2__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.2}/PKG-INFO +1 -1
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/bytecode.hpp +44 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/function_builtins.hpp +27 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/pyproject.toml +1 -1
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/builtins/function_builtins.cpp +16 -12
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/bytecode_compiler.cpp +61 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/bytecode_vm.cpp +134 -22
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/mesh_check.cpp +191 -47
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_bytecode_compiler.cpp +97 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_mesh_check.cpp +40 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/.github/workflows/wheels.yml +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/.gitignore +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/.gitmodules +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/LICENSE +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/README.md +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/bindings/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/bindings/ast_to_py.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/bindings/module.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/cmake/embed_font.cmake +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/examples/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/examples/eval_perf_benchmark.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/examples/manifold_cache_reuse.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/examples/minimal_debugger.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/.gitignore +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/README.md +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/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.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/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.2}/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.2}/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.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope_table.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/src/api.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/src/comments.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/src/position.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/src/scope.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/tests/test_render_expression.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/bytecode_vm.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/colored_body.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/evaluator.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/export.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/font_match.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/format_closure.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/freetype_font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/mesh_check.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/profile.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/scope_trail.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/segments.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/utf8.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/value.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/python/openscad_cpp_evaluator/__init__.py +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/resources/fonts/LICENSE +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/resources/fonts/LiberationSans-Regular.ttf +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/builtins/booleans.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/builtins/builtins.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/builtins/call_args.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/builtins/color.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/builtins/control.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/builtins/dxf_dim.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/builtins/extrude.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/builtins/import.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/builtins/modifiers.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/builtins/primitives_2d.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/builtins/primitives_3d.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/builtins/registry.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/builtins/roof.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/builtins/segments.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/builtins/surface.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/builtins/text.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/builtins/topology.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/builtins/transforms.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/colored_body.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/csg_generate.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/csg_resolve.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/css_colors.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/debug/debug_repl.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/debug_profile.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/eval_context.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/eval_error.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/eval_use.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/export.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/format_closure.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/import/dxf_import.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/import/mesh_import.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/import/surface_load.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/import/svg_import.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/measure_geometry.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/stmt_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/text/font_match.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/text/freetype_font_provider.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/text/text_metrics.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/user_calls.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/utf8.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/value.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/src/zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_booleans.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_children_separate.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_cli.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_control_flow.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_csg_tree.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_debug_hooks.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_dxf_svg_import.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_eval_context.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_export.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_extrude_roof.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_feature_detection.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_import_export.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_include_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_multi_color_merge.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_primitives.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_profiling.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_python_bindings.py +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_render_expr.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_scope_trail.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_scoping.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_surface.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_tail_calls.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_text.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_transforms.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_unexpected_args.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_use.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_value.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_viewport_params.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tests/test_zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tools/cli/cli_lib.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tools/cli/cli_lib.hpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-1.6.1 → openscad_cpp_evaluator-1.7.2}/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,49 @@ 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
|
+
// Any FURTHER parameters of the same name. Normally empty, but a
|
|
820
|
+
// declaration may repeat a parameter name -- BOSL2's
|
|
821
|
+
// regular_prism() declares both `length` and `height` twice --
|
|
822
|
+
// and the name-matching path this replaced bound every one of
|
|
823
|
+
// them, because it walked the parameter list asking "is there a
|
|
824
|
+
// bound argument called this?" rather than the other way round.
|
|
825
|
+
// Binding only the first silently left the body reading undef
|
|
826
|
+
// from whichever slot the duplicate name finally resolved to.
|
|
827
|
+
std::vector<int> alsoParams;
|
|
828
|
+
bool toDyn = false; // instead bind by name into ctx.dyn ($-named, undeclared)
|
|
829
|
+
bool warnUnexpectedNamed = false;
|
|
830
|
+
bool warnTooManyPositional = false;
|
|
831
|
+
};
|
|
832
|
+
std::vector<ArgBind> argBinds;
|
|
833
|
+
bool hasArgPlan = false; // argBinds is authoritative (it is empty for a zero-argument call too)
|
|
790
834
|
};
|
|
791
835
|
|
|
792
836
|
// 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.2}/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,59 @@
|
|
|
20
20
|
namespace oscadeval {
|
|
21
21
|
|
|
22
22
|
namespace {
|
|
23
|
+
// Records every parameter called `name`, not just the first. See
|
|
24
|
+
// CompiledChunk::CallSite::ArgBind::alsoParams for why there can be more
|
|
25
|
+
// than one.
|
|
26
|
+
void bindEveryParamNamed(CompiledChunk::CallSite::ArgBind& b,
|
|
27
|
+
const std::vector<std::unique_ptr<oscad::ParameterDeclaration>>& params,
|
|
28
|
+
const std::string& name) {
|
|
29
|
+
for (size_t p = 0; p < params.size(); ++p) {
|
|
30
|
+
if (params[p]->name->name != name) continue;
|
|
31
|
+
if (b.paramIndex < 0) {
|
|
32
|
+
b.paramIndex = static_cast<int>(p);
|
|
33
|
+
} else {
|
|
34
|
+
b.alsoParams.push_back(static_cast<int>(p));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Replays buildBoundArgs' own positional/named matching rule (bytecode_vm.cpp)
|
|
40
|
+
// against a parameter list known at compile time, recording the answer per
|
|
41
|
+
// argument instead of recomputing it per call. The rule, unchanged: a named
|
|
42
|
+
// argument binds the parameter of that name, warning when there is none and
|
|
43
|
+
// the name is not a $-config variable; a positional argument binds the
|
|
44
|
+
// parameter at its own positional index, warning once when it runs past the
|
|
45
|
+
// end; an undeclared $-name still reaches ctx.dyn; anything else is dropped.
|
|
46
|
+
// A later argument writing the same parameter still wins, because both bind
|
|
47
|
+
// the same slot in order.
|
|
48
|
+
void planCallSiteArgs(CompiledChunk::CallSite& site,
|
|
49
|
+
const std::vector<std::unique_ptr<oscad::ParameterDeclaration>>& params) {
|
|
50
|
+
const size_t nparams = params.size();
|
|
51
|
+
size_t positionalIdx = 0;
|
|
52
|
+
site.argBinds.resize(site.argNames.size());
|
|
53
|
+
for (size_t i = 0; i < site.argNames.size(); ++i) {
|
|
54
|
+
CompiledChunk::CallSite::ArgBind& b = site.argBinds[i];
|
|
55
|
+
if (site.argNames[i]) {
|
|
56
|
+
const std::string& name = *site.argNames[i];
|
|
57
|
+
bindEveryParamNamed(b, params, name);
|
|
58
|
+
const bool found = b.paramIndex >= 0;
|
|
59
|
+
b.warnUnexpectedNamed = !found && !isConfigVariable(name);
|
|
60
|
+
b.toDyn = !found && !name.empty() && name[0] == '$';
|
|
61
|
+
} else {
|
|
62
|
+
if (positionalIdx < nparams) {
|
|
63
|
+
// By NAME, not just by index: a positional argument landing on
|
|
64
|
+
// a repeated name filled every parameter of that name too,
|
|
65
|
+
// because the old path keyed its bound arguments by name.
|
|
66
|
+
bindEveryParamNamed(b, params, params[positionalIdx]->name->name);
|
|
67
|
+
} else if (positionalIdx == nparams) {
|
|
68
|
+
b.warnTooManyPositional = true;
|
|
69
|
+
}
|
|
70
|
+
++positionalIdx;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
site.hasArgPlan = true;
|
|
74
|
+
}
|
|
75
|
+
|
|
23
76
|
|
|
24
77
|
// Thrown by compileExpr wherever it hits a construct this phase doesn't
|
|
25
78
|
// compile yet -- tryCompileFunction catches it and returns nullopt (falls
|
|
@@ -601,6 +654,11 @@ public:
|
|
|
601
654
|
// call-site interleaved order, not resolveArgs'
|
|
602
655
|
// split positional/named CallArgs shape).
|
|
603
656
|
site.isBuiltin = true;
|
|
657
|
+
// Resolve the callee here rather than per call; see
|
|
658
|
+
// CallSite's own doc comment (bytecode.hpp).
|
|
659
|
+
site.builtinId = builtinFnIdFor(calleeName);
|
|
660
|
+
site.declaredParams = builtinParamNames(calleeName);
|
|
661
|
+
site.isObjectBuiltin = (calleeName == "object");
|
|
604
662
|
isStatic = true;
|
|
605
663
|
}
|
|
606
664
|
// Anything else stays dynamic: a function-literal value,
|
|
@@ -674,6 +732,9 @@ public:
|
|
|
674
732
|
}
|
|
675
733
|
}
|
|
676
734
|
}
|
|
735
|
+
// Resolve every argument to its parameter now; see
|
|
736
|
+
// CallSite::argBinds (bytecode.hpp) for why.
|
|
737
|
+
if (site.decl) planCallSiteArgs(site, site.decl->parameters);
|
|
677
738
|
int siteIdx = static_cast<int>(chunk_.callSites.size());
|
|
678
739
|
chunk_.callSites.push_back(std::move(site));
|
|
679
740
|
// 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,71 @@ 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
|
+
// The duplicate-name case (alsoParams) needs the value more than
|
|
155
|
+
// once, so it is copied there and only the last one moves.
|
|
156
|
+
for (const int extra : b.alsoParams) {
|
|
157
|
+
const CompiledChunk::Param& e = chunk.params[static_cast<size_t>(extra)];
|
|
158
|
+
if (e.isDyn) {
|
|
159
|
+
ctx.dyn->set(e.name, args[i]);
|
|
160
|
+
} else {
|
|
161
|
+
frame.slots[static_cast<size_t>(e.slot)] = args[i];
|
|
162
|
+
}
|
|
163
|
+
frame.bound[static_cast<size_t>(extra)] = true;
|
|
164
|
+
}
|
|
165
|
+
const CompiledChunk::Param& p = chunk.params[static_cast<size_t>(b.paramIndex)];
|
|
166
|
+
if (p.isDyn) {
|
|
167
|
+
ctx.dyn->set(p.name, std::move(args[i]));
|
|
168
|
+
} else {
|
|
169
|
+
frame.slots[static_cast<size_t>(p.slot)] = std::move(args[i]);
|
|
170
|
+
}
|
|
171
|
+
frame.bound[static_cast<size_t>(b.paramIndex)] = true;
|
|
172
|
+
} else if (b.toDyn) {
|
|
173
|
+
ctx.dyn->set(*site.argNames[i], std::move(args[i]));
|
|
174
|
+
}
|
|
175
|
+
// else: an undeclared plain name, or a positional past the end --
|
|
176
|
+
// dropped, exactly as the name-matching path drops it.
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
111
180
|
// Same, but for a call site whose arguments are still raw AST (evaluated
|
|
112
181
|
// here against `callerCtx`) -- only ever used by runCompiledFunction's own
|
|
113
182
|
// entry point (a top-level call with raw AST arguments, mirroring
|
|
@@ -249,7 +318,7 @@ void pushBareFrame(Evaluator& ev, const CompiledChunk& chunk, const std::vector<
|
|
|
249
318
|
// own parameters exactly (a FunctionDeclaration's decl/*decl.expr, or a
|
|
250
319
|
// FunctionLiteral's funcNode/*funcNode.body).
|
|
251
320
|
void pushBracketedCallFrame(Evaluator& ev, const CompiledChunk& chunk, const oscad::ASTNode& declNode,
|
|
252
|
-
const oscad::Expression& bodyExpr, const std::string& name,
|
|
321
|
+
const oscad::Expression& bodyExpr, const std::string& name, const FrameArgs& fargs,
|
|
253
322
|
EvalContext& callerCtx, const oscad::Scope* fnScope,
|
|
254
323
|
const std::shared_ptr<TrailView<Value>>& capturedLet, const oscad::Position* callPos) {
|
|
255
324
|
if (ev.vmCallStack_.size() >= Evaluator::kMaxVmCallStackDepth) {
|
|
@@ -274,7 +343,11 @@ void pushBracketedCallFrame(Evaluator& ev, const CompiledChunk& chunk, const osc
|
|
|
274
343
|
frame->tailHopGuard = 0;
|
|
275
344
|
frame->logicalName = name;
|
|
276
345
|
frame->hopEligible = true; // just pushed a fresh, correctly-named callStack_ entry
|
|
277
|
-
|
|
346
|
+
if (fargs.site) {
|
|
347
|
+
bindPlannedArgsIntoFrame(chunk, *fargs.site, fargs.args, fargs.argCount, *frame);
|
|
348
|
+
} else {
|
|
349
|
+
bindBoundArgsIntoFrame(chunk, *fargs.bound, *frame);
|
|
350
|
+
}
|
|
278
351
|
applyCompiledDefaultsToFrame(ev, chunk, *frame);
|
|
279
352
|
|
|
280
353
|
// enterUserCall's own bodyCtx must point at frame->ctxChain's OWN
|
|
@@ -802,7 +875,7 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
802
875
|
f.stack.resize(argBase);
|
|
803
876
|
f.stack.push_back(importAsValue(ev, callArgs, *site.callNode));
|
|
804
877
|
++f.pc;
|
|
805
|
-
} else if (site.
|
|
878
|
+
} else if (site.isObjectBuiltin) {
|
|
806
879
|
std::vector<std::pair<std::optional<std::string>, Value>> pairs;
|
|
807
880
|
pairs.reserve(argCount);
|
|
808
881
|
for (size_t i = 0; i < argCount; ++i) pairs.emplace_back(site.argNames[i], std::move(args[i]));
|
|
@@ -812,24 +885,39 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
812
885
|
} else if (site.isBuiltin) {
|
|
813
886
|
CallArgs& callArgs = buildCallArgs(site, args, argCount, f.argScratch);
|
|
814
887
|
f.stack.resize(argBase);
|
|
815
|
-
f.stack.push_back(
|
|
888
|
+
f.stack.push_back(evalBuiltinFunctionResolved(ev, site.builtinId, site.declaredParams,
|
|
889
|
+
site.calleeName, callArgs, *site.callNode));
|
|
816
890
|
++f.pc;
|
|
817
891
|
} else {
|
|
818
|
-
BoundArgs bound = buildBoundArgs(ev, site, args, argCount, site.decl->parameters);
|
|
819
|
-
f.stack.resize(argBase);
|
|
820
892
|
const CompiledChunk* calleeChunk = ev.useBytecodeVm() ? ev.lookupOrCompileChunk(*site.decl) : nullptr;
|
|
821
|
-
if (calleeChunk) {
|
|
893
|
+
if (calleeChunk && site.hasArgPlan) {
|
|
894
|
+
warnPlannedArgs(ev, site, argCount);
|
|
895
|
+
// The hot path: bind straight off this frame's own
|
|
896
|
+
// stack using the site's compile-time plan, then
|
|
897
|
+
// truncate. Truncating FIRST would destroy the very
|
|
898
|
+
// values being bound.
|
|
822
899
|
const oscad::Scope* fnScope = ctx.scopeOf(*site.decl) ? ctx.scopeOf(*site.decl) : ctx.scope;
|
|
823
900
|
pushBracketedCallFrame(ev, *calleeChunk, *site.decl, *site.decl->expr, site.calleeName,
|
|
824
|
-
|
|
901
|
+
FrameArgs{&site, args, argCount, nullptr}, ctx, fnScope, nullptr,
|
|
902
|
+
&site.callNode->position());
|
|
903
|
+
f.stack.resize(argBase);
|
|
825
904
|
// f.pc deliberately NOT advanced -- resumes when the
|
|
826
905
|
// pushed frame completes (see driveVm's own
|
|
827
906
|
// completion branch, above).
|
|
828
907
|
} else {
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
908
|
+
BoundArgs bound = buildBoundArgs(ev, site, args, argCount, site.decl->parameters);
|
|
909
|
+
f.stack.resize(argBase);
|
|
910
|
+
if (calleeChunk) {
|
|
911
|
+
const oscad::Scope* fnScope = ctx.scopeOf(*site.decl) ? ctx.scopeOf(*site.decl) : ctx.scope;
|
|
912
|
+
pushBracketedCallFrame(ev, *calleeChunk, *site.decl, *site.decl->expr, site.calleeName,
|
|
913
|
+
FrameArgs{nullptr, nullptr, 0, &bound}, ctx, fnScope, nullptr,
|
|
914
|
+
&site.callNode->position());
|
|
915
|
+
} else {
|
|
916
|
+
Value result = ev.evalUserFunctionFromBound(site.calleeName, *site.decl, std::move(bound),
|
|
917
|
+
ctx, &site.callNode->position());
|
|
918
|
+
f.stack.push_back(std::move(result));
|
|
919
|
+
++f.pc;
|
|
920
|
+
}
|
|
833
921
|
}
|
|
834
922
|
}
|
|
835
923
|
break;
|
|
@@ -849,7 +937,7 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
849
937
|
if (calleeChunk) {
|
|
850
938
|
const oscad::Scope* fnScope = ctx.scopeOf(funcNode) ? ctx.scopeOf(funcNode) : ctx.scope;
|
|
851
939
|
pushBracketedCallFrame(ev, *calleeChunk, funcNode, *funcNode.body, "<function literal>",
|
|
852
|
-
|
|
940
|
+
FrameArgs{nullptr, nullptr, 0, &bound}, ctx, fnScope, capturedLetTrail(closure), ins.pos);
|
|
853
941
|
} else {
|
|
854
942
|
Value result = ev.evalFunctionLiteralFromBound(closure, std::move(bound), ctx, ins.pos);
|
|
855
943
|
f.stack.push_back(std::move(result));
|
|
@@ -868,8 +956,17 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
868
956
|
const size_t argCount = static_cast<size_t>(ins.b);
|
|
869
957
|
const size_t argBase = f.stack.size() - argCount;
|
|
870
958
|
Value* args = f.stack.data() + argBase; // into f.stack; truncated below once consumed
|
|
871
|
-
|
|
872
|
-
|
|
959
|
+
// A planned site defers both of these: the arguments have
|
|
960
|
+
// to stay live on this frame's own stack until they are
|
|
961
|
+
// bound, and a tail HOP binds into this very frame.
|
|
962
|
+
const bool planned = site.hasArgPlan;
|
|
963
|
+
BoundArgs bound;
|
|
964
|
+
if (planned) {
|
|
965
|
+
warnPlannedArgs(ev, site, argCount); // before recordTailCallHop; see warnPlannedArgs
|
|
966
|
+
} else {
|
|
967
|
+
bound = buildBoundArgs(ev, site, args, argCount, site.decl->parameters);
|
|
968
|
+
f.stack.resize(argBase);
|
|
969
|
+
}
|
|
873
970
|
// Tail-hop-in-place requires f.hopEligible -- a frame
|
|
874
971
|
// that's call-boundary-free (statement expression,
|
|
875
972
|
// assignment block, parameter default) has no
|
|
@@ -898,22 +995,37 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
898
995
|
f.setCode(calleeChunk->bodyCode);
|
|
899
996
|
f.pc = 0;
|
|
900
997
|
f.slots.assign(static_cast<size_t>(calleeChunk->numSlots), Value{});
|
|
901
|
-
f.stack.clear();
|
|
902
998
|
f.bound.assign(calleeChunk->params.size(), false);
|
|
903
999
|
f.accumStack.clear();
|
|
904
1000
|
f.iterLists.assign(static_cast<size_t>(calleeChunk->numIterLists), IterList{});
|
|
905
1001
|
f.ctxChain.push_back(std::move(*hopCtx));
|
|
906
|
-
|
|
1002
|
+
// The stack is cleared AFTER binding on the planned
|
|
1003
|
+
// path: a hop rebinds this same frame, and `args`
|
|
1004
|
+
// still points into the stack it would have wiped.
|
|
1005
|
+
if (planned) {
|
|
1006
|
+
bindPlannedArgsIntoFrame(*calleeChunk, site, args, argCount, f);
|
|
1007
|
+
f.stack.clear();
|
|
1008
|
+
} else {
|
|
1009
|
+
f.stack.clear();
|
|
1010
|
+
bindBoundArgsIntoFrame(*calleeChunk, bound, f);
|
|
1011
|
+
}
|
|
907
1012
|
applyCompiledDefaultsToFrame(ev, *calleeChunk, f);
|
|
908
1013
|
// continue via the outer while -- re-fetches this
|
|
909
1014
|
// same (now-mutated) frame from its new pc=0.
|
|
910
1015
|
} else {
|
|
1016
|
+
if (planned) { // no hop after all -- fall back to name matching
|
|
1017
|
+
// warnPlannedArgs already emitted these above.
|
|
1018
|
+
bound = buildBoundArgs(ev, site, args, argCount, site.decl->parameters,
|
|
1019
|
+
/*emitWarnings=*/false);
|
|
1020
|
+
f.stack.resize(argBase);
|
|
1021
|
+
}
|
|
911
1022
|
const CompiledChunk* fallbackChunk =
|
|
912
1023
|
ev.useBytecodeVm() ? ev.lookupOrCompileChunk(*site.decl) : nullptr;
|
|
913
1024
|
if (fallbackChunk) {
|
|
914
1025
|
const oscad::Scope* fnScope = ctx.scopeOf(*site.decl) ? ctx.scopeOf(*site.decl) : ctx.scope;
|
|
915
1026
|
pushBracketedCallFrame(ev, *fallbackChunk, *site.decl, *site.decl->expr, site.calleeName,
|
|
916
|
-
|
|
1027
|
+
FrameArgs{nullptr, nullptr, 0, &bound}, ctx, fnScope, nullptr,
|
|
1028
|
+
&site.callNode->position());
|
|
917
1029
|
} else {
|
|
918
1030
|
Value result = ev.evalUserFunctionFromBound(site.calleeName, *site.decl, std::move(bound), ctx,
|
|
919
1031
|
&site.callNode->position());
|
|
@@ -960,7 +1072,7 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
960
1072
|
if (fallbackChunk) {
|
|
961
1073
|
const oscad::Scope* fnScope = ctx.scopeOf(funcNode) ? ctx.scopeOf(funcNode) : ctx.scope;
|
|
962
1074
|
pushBracketedCallFrame(ev, *fallbackChunk, funcNode, *funcNode.body, "<function literal>",
|
|
963
|
-
|
|
1075
|
+
FrameArgs{nullptr, nullptr, 0, &bound}, ctx, fnScope, capturedLetTrail(closure), ins.pos);
|
|
964
1076
|
} else {
|
|
965
1077
|
Value result = ev.evalFunctionLiteralFromBound(closure, std::move(bound), ctx, ins.pos);
|
|
966
1078
|
f.stack.push_back(std::move(result));
|