openscad-cpp-evaluator 0.4.8__tar.gz → 0.4.9__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.
Files changed (195) hide show
  1. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/PKG-INFO +1 -1
  2. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/scope_trail.hpp +73 -9
  3. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/pyproject.toml +1 -1
  4. openscad_cpp_evaluator-0.4.9/tests/test_scope_trail.cpp +151 -0
  5. openscad_cpp_evaluator-0.4.8/tests/test_scope_trail.cpp +0 -79
  6. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/.github/workflows/ci.yml +0 -0
  7. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/.github/workflows/wheels.yml +0 -0
  8. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/.gitignore +0 -0
  9. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/.gitmodules +0 -0
  10. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/CLAUDE.md +0 -0
  11. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/CMakeLists.txt +0 -0
  12. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/LICENSE +0 -0
  13. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/README.md +0 -0
  14. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/bindings/CMakeLists.txt +0 -0
  15. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/bindings/module.cpp +0 -0
  16. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/cmake/embed_font.cmake +0 -0
  17. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/examples/CMakeLists.txt +0 -0
  18. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/examples/eval_perf_benchmark.cpp +0 -0
  19. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/examples/manifold_cache_reuse.cpp +0 -0
  20. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/examples/minimal_debugger.cpp +0 -0
  21. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
  22. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/.gitignore +0 -0
  23. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/CLAUDE.md +0 -0
  24. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
  25. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/README.md +0 -0
  26. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
  27. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
  28. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
  29. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
  30. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
  31. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
  32. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
  33. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
  34. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
  35. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
  36. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
  37. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
  38. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
  39. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
  40. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
  41. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
  42. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/src/api.cpp +0 -0
  43. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
  44. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
  45. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
  46. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
  47. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
  48. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
  49. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
  50. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
  51. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/src/comments.cpp +0 -0
  52. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
  53. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
  54. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
  55. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
  56. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
  57. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
  58. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
  59. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/src/position.cpp +0 -0
  60. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
  61. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/src/scope.cpp +0 -0
  62. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
  63. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
  64. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
  65. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
  66. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
  67. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
  68. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
  69. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
  70. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
  71. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
  72. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
  73. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
  74. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
  75. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
  76. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
  77. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
  78. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
  79. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
  80. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
  81. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
  82. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
  83. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
  84. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
  85. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
  86. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
  87. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
  88. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/bytecode.hpp +0 -0
  89. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
  90. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/bytecode_vm.hpp +0 -0
  91. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
  92. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/colored_body.hpp +0 -0
  93. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
  94. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
  95. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
  96. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
  97. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
  98. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
  99. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
  100. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
  101. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
  102. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/evaluator.hpp +0 -0
  103. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/export.hpp +0 -0
  104. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
  105. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
  106. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
  107. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
  108. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
  109. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
  110. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/profile.hpp +0 -0
  111. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/segments.hpp +0 -0
  112. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/stb_font_provider.hpp +0 -0
  113. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
  114. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
  115. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/value.hpp +0 -0
  116. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
  117. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/python/openscad_cpp_evaluator/__init__.py +0 -0
  118. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/resources/fonts/LICENSE +0 -0
  119. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/resources/fonts/LiberationSans-Regular.ttf +0 -0
  120. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/CMakeLists.txt +0 -0
  121. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/builtins/booleans.cpp +0 -0
  122. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/builtins/builtins.hpp +0 -0
  123. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/builtins/call_args.cpp +0 -0
  124. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/builtins/color.cpp +0 -0
  125. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/builtins/control.cpp +0 -0
  126. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/builtins/extrude.cpp +0 -0
  127. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/builtins/function_builtins.cpp +0 -0
  128. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/builtins/import.cpp +0 -0
  129. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/builtins/modifiers.cpp +0 -0
  130. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/builtins/primitives_2d.cpp +0 -0
  131. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/builtins/primitives_3d.cpp +0 -0
  132. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/builtins/registry.cpp +0 -0
  133. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/builtins/roof.cpp +0 -0
  134. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/builtins/segments.cpp +0 -0
  135. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/builtins/surface.cpp +0 -0
  136. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/builtins/text.cpp +0 -0
  137. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/builtins/topology.cpp +0 -0
  138. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/builtins/transforms.cpp +0 -0
  139. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/bytecode_compiler.cpp +0 -0
  140. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/bytecode_vm.cpp +0 -0
  141. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/colored_body.cpp +0 -0
  142. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/csg_generate.cpp +0 -0
  143. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/csg_resolve.cpp +0 -0
  144. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/css_colors.cpp +0 -0
  145. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/debug/debug_repl.cpp +0 -0
  146. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/debug_profile.cpp +0 -0
  147. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/eval_context.cpp +0 -0
  148. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/eval_error.cpp +0 -0
  149. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/eval_use.cpp +0 -0
  150. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/export.cpp +0 -0
  151. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/expr_eval.cpp +0 -0
  152. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/import/dxf_import.cpp +0 -0
  153. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/import/mesh_import.cpp +0 -0
  154. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/import/surface_load.cpp +0 -0
  155. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/import/svg_import.cpp +0 -0
  156. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/manifold_cache.cpp +0 -0
  157. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/stmt_eval.cpp +0 -0
  158. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/text/stb_font_provider.cpp +0 -0
  159. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/text/text_metrics.cpp +0 -0
  160. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/user_calls.cpp +0 -0
  161. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/value.cpp +0 -0
  162. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/src/zip_stored.cpp +0 -0
  163. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/CMakeLists.txt +0 -0
  164. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_booleans.cpp +0 -0
  165. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_bytecode_compiler.cpp +0 -0
  166. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_cli.cpp +0 -0
  167. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_control_flow.cpp +0 -0
  168. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_csg_tree.cpp +0 -0
  169. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_debug_hooks.cpp +0 -0
  170. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_dxf_svg_import.cpp +0 -0
  171. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_eval_context.cpp +0 -0
  172. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_export.cpp +0 -0
  173. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_expr_eval.cpp +0 -0
  174. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_extrude_roof.cpp +0 -0
  175. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_function_builtins.cpp +0 -0
  176. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_helpers.hpp +0 -0
  177. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_import_export.cpp +0 -0
  178. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_manifold_cache.cpp +0 -0
  179. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_multi_color_merge.cpp +0 -0
  180. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_primitives.cpp +0 -0
  181. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_profiling.cpp +0 -0
  182. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_python_bindings.py +0 -0
  183. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_scoping.cpp +0 -0
  184. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_surface.cpp +0 -0
  185. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_tail_calls.cpp +0 -0
  186. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_text.cpp +0 -0
  187. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_transforms.cpp +0 -0
  188. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_use.cpp +0 -0
  189. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_value.cpp +0 -0
  190. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_viewport_params.cpp +0 -0
  191. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tests/test_zip_stored.cpp +0 -0
  192. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tools/cli/CMakeLists.txt +0 -0
  193. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tools/cli/cli_lib.cpp +0 -0
  194. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tools/cli/cli_lib.hpp +0 -0
  195. {openscad_cpp_evaluator-0.4.8 → openscad_cpp_evaluator-0.4.9}/tools/cli/main.cpp +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openscad_cpp_evaluator
3
- Version: 0.4.8
3
+ Version: 0.4.9
4
4
  Summary: C++ OpenSCAD evaluator with Python bindings
5
5
  Author: NeuSCAD Contributors
6
6
  License-Expression: MIT
@@ -79,18 +79,46 @@ public:
79
79
 
80
80
  // Pops every entry pushed at `level`, across every name that was
81
81
  // touched at that level (dirty_[level], recorded by set() above) --
82
- // O(bindings made at this level), not O(total names). Left-in-place,
83
- // possibly-now-empty per-name vectors are NOT erased from `stacks_`:
84
- // ponytail: real scripts rebind the same small name set repeatedly
85
- // (loop vars, $fn, ...), so paying one erase+reinsert per pop is pure
86
- // waste; revisit only if memory footprint (not speed) ever measurably
87
- // matters for a script with a huge, non-repeating variable vocabulary.
82
+ // O(bindings made at this level) in the common case, not O(total
83
+ // names). Left-in-place, possibly-now-empty per-name vectors are NOT
84
+ // erased from `stacks_`: ponytail: real scripts rebind the same small
85
+ // name set repeatedly (loop vars, $fn, ...), so paying one
86
+ // erase+reinsert per pop is pure waste; revisit only if memory
87
+ // footprint (not speed) ever measurably matters for a script with a
88
+ // huge, non-repeating variable vocabulary.
89
+ //
90
+ // Removes the entry matching THIS level specifically, not just
91
+ // whatever's currently last -- these can differ once an escaping
92
+ // closure is in play (TrailView::parentView_, see its own doc
93
+ // comment): a closure can keep one ancestor level alive well past its
94
+ // own natural (LIFO, call/return-order) lifetime, while an EARLIER,
95
+ // otherwise-unrelated level that happens to touch the same NAME pops
96
+ // normally in the meantime. If that earlier level's own entry is no
97
+ // longer physically last in `vec` (the kept-alive later one is still
98
+ // sitting on top), a blind pop_back() would silently remove the WRONG
99
+ // entry -- the still-live, captured one, not the one actually being
100
+ // popped. Caught by a real repro: `function make(x,table)=
101
+ // let(table=...) x!=undef? make(table=table)(v=x) : function(v)
102
+ // v!=undef? let(nt=concat(table,[v])) make(table=nt) : table;` --
103
+ // invoking the returned closure read undef for a `table` that was
104
+ // bound directly at the closure's OWN captured level (not even an
105
+ // ancestor hop away), because an unrelated, earlier `table` push from
106
+ // a sibling recursive call got popped out of order and silently ate
107
+ // it. Scans from the back (the common case -- this level's own push
108
+ // usually IS at or near the top) rather than assuming position 0.
88
109
  void popLevel(int level) {
89
110
  auto it = dirty_.find(level);
90
111
  if (it != dirty_.end()) {
91
112
  for (const std::string& name : it->second) {
92
113
  auto sit = stacks_.find(name);
93
- if (sit != stacks_.end() && !sit->second.empty()) sit->second.pop_back();
114
+ if (sit == stacks_.end()) continue;
115
+ std::vector<Entry>& vec = sit->second;
116
+ for (auto rit = vec.rbegin(); rit != vec.rend(); ++rit) {
117
+ if (rit->level == level) {
118
+ vec.erase(std::next(rit).base());
119
+ break;
120
+ }
121
+ }
94
122
  }
95
123
  dirty_.erase(it);
96
124
  }
@@ -191,7 +219,7 @@ private:
191
219
  // allocations each down to 4 trails * 1) with no change to the
192
220
  // ancestry-walk/isolation logic itself.
193
221
  template <typename T>
194
- class TrailView {
222
+ class TrailView : public std::enable_shared_from_this<TrailView<T>> {
195
223
  public:
196
224
  static std::shared_ptr<TrailView<T>> makeRoot() {
197
225
  auto storage = std::make_shared<ScopeTrailStorage<T>>();
@@ -206,9 +234,36 @@ public:
206
234
  // chain through this view's own level (childCtx()/letChildCtx() --
207
235
  // reads see through to the caller's own bindings, while only this
208
236
  // scope's own writes get popped away on exit).
237
+ //
238
+ // The child also holds a shared_ptr back to THIS view (parentView_,
239
+ // isolate=false only) -- not just the ancestor level NUMBER already
240
+ // tracked in ScopeTrailStorage::parent_. Ancestry-chain VISIBILITY
241
+ // (lookup()'s walk) only needs the number; but an escaping closure
242
+ // (Closure::capturedLet, value.hpp) keeps exactly one TrailView alive
243
+ // past its own scope's normal exit by holding an extra shared_ptr
244
+ // reference to it -- and that view is very often an intermediate
245
+ // level (e.g. a let()'s own child level, one hop below the call level
246
+ // that actually bound the captured variable, see EvalContext::
247
+ // letChildCtx()), not the outermost one. Without parentView_, nothing
248
+ // keeps that OUTER level's own TrailView alive once its own creating
249
+ // call returns; ~TrailView() pops ITS bindings from ScopeTrailStorage
250
+ // (erasing the very data the still-alive child's ancestry walk needs)
251
+ // even though the walk can still numerically reach that ancestor level
252
+ // via ScopeTrailStorage::parent_ (that map entry is untouched -- only
253
+ // the DATA is gone). Caught by a closure created inside a let()
254
+ // nested one level inside its own enclosing call reading undef for a
255
+ // variable bound at the call's own (now-popped) level, not the let()'s
256
+ // (kept alive) one. Holding parentView_ makes keeping a leaf level
257
+ // alive transitively keep its whole ancestor chain's data alive too,
258
+ // cascading in the same reverse-of-creation order an ordinary nested
259
+ // call/return already unwinds in (member destruction order below), so
260
+ // normal (non-escaping) scopes pop exactly as before -- this only
261
+ // changes what happens when something holds an EXTRA reference.
209
262
  std::shared_ptr<TrailView<T>> openChild(bool isolate) const {
210
263
  int level = storage_->openLevel(isolate ? 0 : level_);
211
- return std::make_shared<TrailView<T>>(storage_, level);
264
+ auto child = std::make_shared<TrailView<T>>(storage_, level);
265
+ if (!isolate) child->parentView_ = this->shared_from_this();
266
+ return child;
212
267
  }
213
268
 
214
269
  TrailView(std::shared_ptr<ScopeTrailStorage<T>> storage, int level)
@@ -233,6 +288,15 @@ public:
233
288
  private:
234
289
  std::shared_ptr<ScopeTrailStorage<T>> storage_;
235
290
  int level_;
291
+ // Declared LAST so it's destroyed FIRST (reverse declaration order),
292
+ // i.e. immediately after ~TrailView()'s own body (which pops THIS
293
+ // view's own level) -- releasing (and, if this was the last
294
+ // reference, cascading into) the parent's own pop right away, in the
295
+ // same order a normal nested call/return already unwinds in. `const`:
296
+ // openChild() is itself const, so shared_from_this() resolves to the
297
+ // const overload -- only lifetime-extension is needed here, never
298
+ // mutation through this pointer.
299
+ std::shared_ptr<const TrailView<T>> parentView_;
236
300
  };
237
301
 
238
302
  // Shared bidirectional name<->small-int interning table for $-prefixed
@@ -4,7 +4,7 @@ build-backend = "scikit_build_core.build"
4
4
 
5
5
  [project]
6
6
  name = "openscad_cpp_evaluator"
7
- version = "0.4.8"
7
+ version = "0.4.9"
8
8
  description = "C++ OpenSCAD evaluator with Python bindings"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -0,0 +1,151 @@
1
+ #include "openscad_cpp_evaluator/scope_trail.hpp"
2
+
3
+ #include <gtest/gtest.h>
4
+
5
+ namespace oscadeval {
6
+ namespace {
7
+
8
+ TEST(ScopeTrailStorage, SetAtSameLevelOverwritesLatestValue) {
9
+ ScopeTrailStorage<int> storage;
10
+ const int level = storage.openLevel(0);
11
+ storage.set("i", 1, level);
12
+ storage.set("i", 2, level);
13
+ storage.set("i", 3, level);
14
+ ASSERT_NE(storage.lookup("i", level), nullptr);
15
+ EXPECT_EQ(*storage.lookup("i", level), 3);
16
+ }
17
+
18
+ TEST(ScopeTrailStorage, SetAtSameLevelDoesNotAccumulateEntries) {
19
+ // The actual optimization this session added: repeated set() calls at
20
+ // the SAME level (a for-loop variable rebound every iteration without
21
+ // opening a new level, or sibling same-block statements reassigning
22
+ // the same name) must overwrite in place, not grow the underlying
23
+ // stack -- verified via the test-only accessor, since correctness
24
+ // alone (SetAtSameLevelOverwritesLatestValue above) can't distinguish
25
+ // "overwrote in place" from "pushed and lookup() happens to find the
26
+ // newest one anyway."
27
+ ScopeTrailStorage<int> storage;
28
+ const int level = storage.openLevel(0);
29
+ for (int i = 0; i < 1000; ++i) storage.set("i", i, level);
30
+ EXPECT_EQ(storage.debugEntryCountForTesting("i"), 1u);
31
+ }
32
+
33
+ TEST(ScopeTrailStorage, SetAtANewLevelStillPushes) {
34
+ // The optimization must not collapse GENUINE nested bindings -- a
35
+ // child level's own set() for the same name is a real new binding
36
+ // (must be poppable back to the parent's value), not a same-level
37
+ // rebind.
38
+ ScopeTrailStorage<int> storage;
39
+ const int parentLevel = storage.openLevel(0);
40
+ storage.set("x", 1, parentLevel);
41
+ const int childLevel = storage.openLevel(parentLevel);
42
+ storage.set("x", 2, childLevel);
43
+ EXPECT_EQ(storage.debugEntryCountForTesting("x"), 2u);
44
+ ASSERT_NE(storage.lookup("x", childLevel), nullptr);
45
+ EXPECT_EQ(*storage.lookup("x", childLevel), 2);
46
+ storage.popLevel(childLevel);
47
+ ASSERT_NE(storage.lookup("x", parentLevel), nullptr);
48
+ EXPECT_EQ(*storage.lookup("x", parentLevel), 1);
49
+ }
50
+
51
+ TEST(ScopeTrailStorage, PopLevelAfterManySameLevelSetsRestoresParentValue) {
52
+ // The end-to-end correctness case a for-loop actually exercises: many
53
+ // same-level rebinds of the loop variable, then the level closes
54
+ // (loop exits) -- the parent's own binding for that name (if any) must
55
+ // resurface untouched, and the now-closed level's value must not leak.
56
+ ScopeTrailStorage<int> storage;
57
+ const int parentLevel = storage.openLevel(0);
58
+ storage.set("i", -1, parentLevel);
59
+ const int loopLevel = storage.openLevel(parentLevel);
60
+ for (int i = 0; i < 999; ++i) storage.set("i", i, loopLevel);
61
+ ASSERT_NE(storage.lookup("i", loopLevel), nullptr);
62
+ EXPECT_EQ(*storage.lookup("i", loopLevel), 998);
63
+ storage.popLevel(loopLevel);
64
+ ASSERT_NE(storage.lookup("i", parentLevel), nullptr);
65
+ EXPECT_EQ(*storage.lookup("i", parentLevel), -1);
66
+ }
67
+
68
+ TEST(IndexedScopeTrailStorage, SetAtSameLevelDoesNotAccumulateEntries) {
69
+ auto intern = std::make_shared<DynNameIntern>();
70
+ IndexedScopeTrailStorage<int> storage(intern);
71
+ const int level = storage.openLevel(0);
72
+ for (int i = 0; i < 1000; ++i) storage.set("$fn", i, level);
73
+ EXPECT_EQ(storage.debugEntryCountForTesting("$fn"), 1u);
74
+ ASSERT_NE(storage.lookup("$fn", level), nullptr);
75
+ EXPECT_EQ(*storage.lookup("$fn", level), 999);
76
+ }
77
+
78
+ // A captured (closure) level's own ancestor must stay alive even after
79
+ // EVERY other TrailView referencing that ancestor has gone out of scope --
80
+ // see TrailView::openChild's own doc comment (parentView_) for why. This
81
+ // reproduces the exact level shape a real escaping-closure scenario builds
82
+ // (traced from `function make(x,table)=let(table=...) x!=undef?
83
+ // make(table=table)(v=x) : function(v) v!=undef?
84
+ // let(nt=concat(table,[v])) make(table=nt) : table;`), with each C++ scope
85
+ // block standing in for one step of Evaluator::evalFunctionBodyTrampoline's
86
+ // own `chain` vector going out of scope once its owning call returns:
87
+ // 1) M1_CALL (isolated call level for the outer make(10))
88
+ // 2) M1_LET (its own let(table=...) child level)
89
+ // 3) M2_CALL (a NESTED, non-tail recursive make(table=table) call --
90
+ // isolated, since callCtxFor's sameSpan check correctly refuses to
91
+ // treat same-function recursion as "still nested")
92
+ // 4) M2_LET (that call's own let(table=...))
93
+ // 5) C1_CALL (capturedLet-rooted: invoking the closure captured at
94
+ // M2_LET, continuing ITS ancestry rather than the caller's)
95
+ // 6) C1_LET (that invocation's own let(newtable=...))
96
+ // 7) M3_CALL (a SECOND tail-hop into the NAMED function make(table=
97
+ // newtable) -- also isolated, not capturedLet-based)
98
+ // 8) M3_LET (that hop's own let(table=...) -- this is the level the
99
+ // SECOND closure, C2, actually captures)
100
+ // After every one of 1-8 goes out of scope except the shared_ptr a
101
+ // "Closure" would hold (mirroring M3_LET, i.e. what capturedLet points
102
+ // to), invoking that closure must still resolve `table` -- bound all the
103
+ // way back at M3_LET itself, so this specific case doesn't even need to
104
+ // walk past one level, but the SURROUNDING chain (steps 1-7) must not have
105
+ // corrupted or blocked that walk on its own way out.
106
+ TEST(TrailView, EscapingClosureThroughDoubleTailHopStillSeesAncestorAfterChainUnwinds) {
107
+ std::shared_ptr<TrailView<int>> capturedLet;
108
+ {
109
+ auto root = TrailView<int>::makeRoot();
110
+ auto m1Call = root->openChild(/*isolate=*/true);
111
+ m1Call->set("x", 10);
112
+ auto m1Let = m1Call->openChild(/*isolate=*/false);
113
+ m1Let->set("table", 123);
114
+ auto m2Call = m1Let->openChild(/*isolate=*/true);
115
+ m2Call->set("table", 123);
116
+ auto m2Let = m2Call->openChild(/*isolate=*/false);
117
+ m2Let->set("table", 123);
118
+ auto c1Call = m2Let->openChild(/*isolate=*/false);
119
+ c1Call->set("v", 10);
120
+ auto c1Let = c1Call->openChild(/*isolate=*/false);
121
+ c1Let->set("newtable", 1230);
122
+ auto m3Call = c1Let->openChild(/*isolate=*/true);
123
+ m3Call->set("table", 1230);
124
+ auto m3Let = m3Call->openChild(/*isolate=*/false);
125
+ m3Let->set("table", 1230);
126
+ capturedLet = m3Let;
127
+ } // every level above except capturedLet's own (m3Let) goes out of scope here
128
+
129
+ auto c2Call = capturedLet->openChild(/*isolate=*/false);
130
+ ASSERT_NE(c2Call->find("table"), nullptr);
131
+ EXPECT_EQ(*c2Call->find("table"), 1230);
132
+ }
133
+
134
+ TEST(TrailView, MinimalTwoLevelKeepAlive) {
135
+ std::shared_ptr<TrailView<int>> captured;
136
+ {
137
+ auto root = TrailView<int>::makeRoot();
138
+ auto parent = root->openChild(/*isolate=*/true);
139
+ parent->set("x", 42);
140
+ auto child = parent->openChild(/*isolate=*/false);
141
+ captured = child;
142
+ }
143
+ auto grandchild = captured->openChild(/*isolate=*/false);
144
+ ASSERT_NE(grandchild->find("x"), nullptr);
145
+ EXPECT_EQ(*grandchild->find("x"), 42);
146
+ }
147
+
148
+ } // namespace
149
+ } // namespace oscadeval
150
+
151
+
@@ -1,79 +0,0 @@
1
- #include "openscad_cpp_evaluator/scope_trail.hpp"
2
-
3
- #include <gtest/gtest.h>
4
-
5
- namespace oscadeval {
6
- namespace {
7
-
8
- TEST(ScopeTrailStorage, SetAtSameLevelOverwritesLatestValue) {
9
- ScopeTrailStorage<int> storage;
10
- const int level = storage.openLevel(0);
11
- storage.set("i", 1, level);
12
- storage.set("i", 2, level);
13
- storage.set("i", 3, level);
14
- ASSERT_NE(storage.lookup("i", level), nullptr);
15
- EXPECT_EQ(*storage.lookup("i", level), 3);
16
- }
17
-
18
- TEST(ScopeTrailStorage, SetAtSameLevelDoesNotAccumulateEntries) {
19
- // The actual optimization this session added: repeated set() calls at
20
- // the SAME level (a for-loop variable rebound every iteration without
21
- // opening a new level, or sibling same-block statements reassigning
22
- // the same name) must overwrite in place, not grow the underlying
23
- // stack -- verified via the test-only accessor, since correctness
24
- // alone (SetAtSameLevelOverwritesLatestValue above) can't distinguish
25
- // "overwrote in place" from "pushed and lookup() happens to find the
26
- // newest one anyway."
27
- ScopeTrailStorage<int> storage;
28
- const int level = storage.openLevel(0);
29
- for (int i = 0; i < 1000; ++i) storage.set("i", i, level);
30
- EXPECT_EQ(storage.debugEntryCountForTesting("i"), 1u);
31
- }
32
-
33
- TEST(ScopeTrailStorage, SetAtANewLevelStillPushes) {
34
- // The optimization must not collapse GENUINE nested bindings -- a
35
- // child level's own set() for the same name is a real new binding
36
- // (must be poppable back to the parent's value), not a same-level
37
- // rebind.
38
- ScopeTrailStorage<int> storage;
39
- const int parentLevel = storage.openLevel(0);
40
- storage.set("x", 1, parentLevel);
41
- const int childLevel = storage.openLevel(parentLevel);
42
- storage.set("x", 2, childLevel);
43
- EXPECT_EQ(storage.debugEntryCountForTesting("x"), 2u);
44
- ASSERT_NE(storage.lookup("x", childLevel), nullptr);
45
- EXPECT_EQ(*storage.lookup("x", childLevel), 2);
46
- storage.popLevel(childLevel);
47
- ASSERT_NE(storage.lookup("x", parentLevel), nullptr);
48
- EXPECT_EQ(*storage.lookup("x", parentLevel), 1);
49
- }
50
-
51
- TEST(ScopeTrailStorage, PopLevelAfterManySameLevelSetsRestoresParentValue) {
52
- // The end-to-end correctness case a for-loop actually exercises: many
53
- // same-level rebinds of the loop variable, then the level closes
54
- // (loop exits) -- the parent's own binding for that name (if any) must
55
- // resurface untouched, and the now-closed level's value must not leak.
56
- ScopeTrailStorage<int> storage;
57
- const int parentLevel = storage.openLevel(0);
58
- storage.set("i", -1, parentLevel);
59
- const int loopLevel = storage.openLevel(parentLevel);
60
- for (int i = 0; i < 999; ++i) storage.set("i", i, loopLevel);
61
- ASSERT_NE(storage.lookup("i", loopLevel), nullptr);
62
- EXPECT_EQ(*storage.lookup("i", loopLevel), 998);
63
- storage.popLevel(loopLevel);
64
- ASSERT_NE(storage.lookup("i", parentLevel), nullptr);
65
- EXPECT_EQ(*storage.lookup("i", parentLevel), -1);
66
- }
67
-
68
- TEST(IndexedScopeTrailStorage, SetAtSameLevelDoesNotAccumulateEntries) {
69
- auto intern = std::make_shared<DynNameIntern>();
70
- IndexedScopeTrailStorage<int> storage(intern);
71
- const int level = storage.openLevel(0);
72
- for (int i = 0; i < 1000; ++i) storage.set("$fn", i, level);
73
- EXPECT_EQ(storage.debugEntryCountForTesting("$fn"), 1u);
74
- ASSERT_NE(storage.lookup("$fn", level), nullptr);
75
- EXPECT_EQ(*storage.lookup("$fn", level), 999);
76
- }
77
-
78
- } // namespace
79
- } // namespace oscadeval