codecin 6.2.2__tar.gz → 6.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (247) hide show
  1. {codecin-6.2.2 → codecin-6.3.1}/CHANGELOG.md +42 -0
  2. {codecin-6.2.2/codecin.egg-info → codecin-6.3.1}/PKG-INFO +3 -5
  3. {codecin-6.2.2 → codecin-6.3.1}/README.md +2 -4
  4. {codecin-6.2.2 → codecin-6.3.1}/codecin/__init__.py +1 -1
  5. {codecin-6.2.2 → codecin-6.3.1}/codecin/cli.py +25 -0
  6. {codecin-6.2.2 → codecin-6.3.1}/codecin/cpu.py +21 -1
  7. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/aot/aot.go +5 -1
  8. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/keyboard.go +10 -1
  9. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/keyboard_other.go +13 -9
  10. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/keyboard_stub.go +3 -0
  11. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/keyboard_test.go +7 -7
  12. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/keyboard_windows.go +30 -18
  13. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/native.go +7 -1
  14. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/version_gen.go +1 -1
  15. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/vm.go +29 -24
  16. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/main.go +14 -8
  17. {codecin-6.2.2 → codecin-6.3.1}/codecin/native.py +6 -3
  18. {codecin-6.2.2 → codecin-6.3.1}/codecin/native_codegen.py +1 -0
  19. {codecin-6.2.2 → codecin-6.3.1/codecin.egg-info}/PKG-INFO +3 -5
  20. {codecin-6.2.2 → codecin-6.3.1}/codecin.egg-info/SOURCES.txt +1 -0
  21. codecin-6.3.1/examples/terminal_cache_demo.cin +135 -0
  22. {codecin-6.2.2 → codecin-6.3.1}/LICENSE +0 -0
  23. {codecin-6.2.2 → codecin-6.3.1}/MANIFEST.in +0 -0
  24. {codecin-6.2.2 → codecin-6.3.1}/codecin/aot.py +0 -0
  25. {codecin-6.2.2 → codecin-6.3.1}/codecin/assembler.py +0 -0
  26. {codecin-6.2.2 → codecin-6.3.1}/codecin/cin.py +0 -0
  27. {codecin-6.2.2 → codecin-6.3.1}/codecin/config.py +0 -0
  28. {codecin-6.2.2 → codecin-6.3.1}/codecin/console.py +0 -0
  29. {codecin-6.2.2 → codecin-6.3.1}/codecin/crom.py +0 -0
  30. {codecin-6.2.2 → codecin-6.3.1}/codecin/cvm.py +0 -0
  31. {codecin-6.2.2 → codecin-6.3.1}/codecin/disasm.py +0 -0
  32. {codecin-6.2.2 → codecin-6.3.1}/codecin/environment.py +0 -0
  33. {codecin-6.2.2 → codecin-6.3.1}/codecin/errors.py +0 -0
  34. {codecin-6.2.2 → codecin-6.3.1}/codecin/isa.py +0 -0
  35. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/array.cin +0 -0
  36. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/bigint.cin +0 -0
  37. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/bits.cin +0 -0
  38. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/bitset.cin +0 -0
  39. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/codec.cin +0 -0
  40. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/combin.cin +0 -0
  41. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/conv.cin +0 -0
  42. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/cppstd.cin +0 -0
  43. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/cstd.cin +0 -0
  44. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/csv.cin +0 -0
  45. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/dp.cin +0 -0
  46. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/ffi.cin +0 -0
  47. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/fmt.cin +0 -0
  48. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/frac.cin +0 -0
  49. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/gostd.cin +0 -0
  50. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/graph.cin +0 -0
  51. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/gui.cin +0 -0
  52. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/hash.cin +0 -0
  53. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/heap.cin +0 -0
  54. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/io.cin +0 -0
  55. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/json.cin +0 -0
  56. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/key.cin +0 -0
  57. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/math.cin +0 -0
  58. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/matrix.cin +0 -0
  59. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/net.cin +0 -0
  60. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/path.cin +0 -0
  61. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/queue.cin +0 -0
  62. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/rand.cin +0 -0
  63. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/set.cin +0 -0
  64. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/sort.cin +0 -0
  65. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/stat.cin +0 -0
  66. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/str.cin +0 -0
  67. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/termux.cin +0 -0
  68. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/test.cin +0 -0
  69. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/text.cin +0 -0
  70. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/time.cin +0 -0
  71. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/token.cin +0 -0
  72. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/tree.cin +0 -0
  73. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/unionfind.cin +0 -0
  74. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/validate.cin +0 -0
  75. {codecin-6.2.2 → codecin-6.3.1}/codecin/lib/vec.cin +0 -0
  76. {codecin-6.2.2 → codecin-6.3.1}/codecin/logger.py +0 -0
  77. {codecin-6.2.2 → codecin-6.3.1}/codecin/memory.py +0 -0
  78. {codecin-6.2.2 → codecin-6.3.1}/codecin/mkn.py +0 -0
  79. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/aot/stub_main.go.txt +0 -0
  80. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/build.ps1 +0 -0
  81. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/build.sh +0 -0
  82. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/compiler/codegen.go +0 -0
  83. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/compiler/compile_test.go +0 -0
  84. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/compiler/parser.go +0 -0
  85. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/compiler/syscalls.go +0 -0
  86. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/compiler/tokenizer.go +0 -0
  87. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/compiler/types.go +0 -0
  88. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/args.go +0 -0
  89. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/audio.go +0 -0
  90. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/audio_other.go +0 -0
  91. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/audio_test.go +0 -0
  92. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/audio_windows.go +0 -0
  93. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/canvas.go +0 -0
  94. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/console_other.go +0 -0
  95. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/console_windows.go +0 -0
  96. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/crom.go +0 -0
  97. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/encode.go +0 -0
  98. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/engine_test.go +0 -0
  99. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/ffi_nocgo.go +0 -0
  100. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/ffi_registry.go +0 -0
  101. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/ffi_unix.go +0 -0
  102. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/ffi_windows.go +0 -0
  103. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/gui.go +0 -0
  104. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/gui_stub.go +0 -0
  105. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/gui_test.go +0 -0
  106. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/gui_windows.go +0 -0
  107. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/gui_x11.go +0 -0
  108. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/host_test.go +0 -0
  109. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/hostcrypto.go +0 -0
  110. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/hostdesktop.go +0 -0
  111. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/hostnet.go +0 -0
  112. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/isa_gen.go +0 -0
  113. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/keyboard_termios_darwin.go +0 -0
  114. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/keyboard_termios_linux.go +0 -0
  115. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/keyboard_windows_test.go +0 -0
  116. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/lineedit.go +0 -0
  117. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/lineedit_test.go +0 -0
  118. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/lineint_unix.go +0 -0
  119. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/lineint_windows.go +0 -0
  120. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/mem_other.go +0 -0
  121. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/mem_windows.go +0 -0
  122. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/netsock.go +0 -0
  123. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/ops_ext.go +0 -0
  124. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/stdin.go +0 -0
  125. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/stdin_other.go +0 -0
  126. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/stdin_windows.go +0 -0
  127. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/system.go +0 -0
  128. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/termux.go +0 -0
  129. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/vkb_darwin.go +0 -0
  130. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/vkb_linux.go +0 -0
  131. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/engine/vkb_stub.go +0 -0
  132. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/go.mod +0 -0
  133. {codecin-6.2.2 → codecin-6.3.1}/codecin/native/ir/ir.go +0 -0
  134. {codecin-6.2.2 → codecin-6.3.1}/codecin/object.py +0 -0
  135. {codecin-6.2.2 → codecin-6.3.1}/codecin/optimizer.py +0 -0
  136. {codecin-6.2.2 → codecin-6.3.1}/codecin/packaging/__init__.py +0 -0
  137. {codecin-6.2.2 → codecin-6.3.1}/codecin/packaging/archive.py +0 -0
  138. {codecin-6.2.2 → codecin-6.3.1}/codecin/packaging/model.py +0 -0
  139. {codecin-6.2.2 → codecin-6.3.1}/codecin/packaging/store.py +0 -0
  140. {codecin-6.2.2 → codecin-6.3.1}/codecin/packaging/toml.py +0 -0
  141. {codecin-6.2.2 → codecin-6.3.1}/codecin/packaging/vcs.py +0 -0
  142. {codecin-6.2.2 → codecin-6.3.1}/codecin/pic.py +0 -0
  143. {codecin-6.2.2 → codecin-6.3.1}/codecin/pic_api.py +0 -0
  144. {codecin-6.2.2 → codecin-6.3.1}/codecin/pic_login.py +0 -0
  145. {codecin-6.2.2 → codecin-6.3.1}/codecin/pic_registry.py +0 -0
  146. {codecin-6.2.2 → codecin-6.3.1}/codecin/registers.py +0 -0
  147. {codecin-6.2.2 → codecin-6.3.1}/codecin/stats.py +0 -0
  148. {codecin-6.2.2 → codecin-6.3.1}/codecin/stdlib.py +0 -0
  149. {codecin-6.2.2 → codecin-6.3.1}/codecin/toolkit.py +0 -0
  150. {codecin-6.2.2 → codecin-6.3.1}/codecin/version.py +0 -0
  151. {codecin-6.2.2 → codecin-6.3.1}/codecin.egg-info/dependency_links.txt +0 -0
  152. {codecin-6.2.2 → codecin-6.3.1}/codecin.egg-info/entry_points.txt +0 -0
  153. {codecin-6.2.2 → codecin-6.3.1}/codecin.egg-info/requires.txt +0 -0
  154. {codecin-6.2.2 → codecin-6.3.1}/codecin.egg-info/top_level.txt +0 -0
  155. {codecin-6.2.2 → codecin-6.3.1}/examples/args_demo.cin +0 -0
  156. {codecin-6.2.2 → codecin-6.3.1}/examples/asm_constants.asm +0 -0
  157. {codecin-6.2.2 → codecin-6.3.1}/examples/bitwise_builtins.cin +0 -0
  158. {codecin-6.2.2 → codecin-6.3.1}/examples/control_flow.cin +0 -0
  159. {codecin-6.2.2 → codecin-6.3.1}/examples/enum_range_for.cin +0 -0
  160. {codecin-6.2.2 → codecin-6.3.1}/examples/gui_demo.cin +0 -0
  161. {codecin-6.2.2 → codecin-6.3.1}/examples/literals_types.cin +0 -0
  162. {codecin-6.2.2 → codecin-6.3.1}/examples/local_audio.cin +0 -0
  163. {codecin-6.2.2 → codecin-6.3.1}/examples/modules_demo.cin +0 -0
  164. {codecin-6.2.2 → codecin-6.3.1}/examples/stdlib_demo.cin +0 -0
  165. {codecin-6.2.2 → codecin-6.3.1}/examples/system_interaction.cin +0 -0
  166. {codecin-6.2.2 → codecin-6.3.1}/misc/vim/ftdetect/codecin.vim +0 -0
  167. {codecin-6.2.2 → codecin-6.3.1}/misc/vim/syntax/cin.vim +0 -0
  168. {codecin-6.2.2 → codecin-6.3.1}/misc/vim/syntax/codecinasm.vim +0 -0
  169. {codecin-6.2.2 → codecin-6.3.1}/misc/vscode-cin/.vscodeignore +0 -0
  170. {codecin-6.2.2 → codecin-6.3.1}/misc/vscode-cin/README.md +0 -0
  171. {codecin-6.2.2 → codecin-6.3.1}/misc/vscode-cin/build.bat +0 -0
  172. {codecin-6.2.2 → codecin-6.3.1}/misc/vscode-cin/language-configuration.json +0 -0
  173. {codecin-6.2.2 → codecin-6.3.1}/misc/vscode-cin/package.json +0 -0
  174. {codecin-6.2.2 → codecin-6.3.1}/misc/vscode-cin/snippets/cin.json +0 -0
  175. {codecin-6.2.2 → codecin-6.3.1}/misc/vscode-cin/syntaxes/cin.tmLanguage.json +0 -0
  176. {codecin-6.2.2 → codecin-6.3.1}/pyproject.toml +0 -0
  177. {codecin-6.2.2 → codecin-6.3.1}/script/bump_version.py +0 -0
  178. {codecin-6.2.2 → codecin-6.3.1}/script/check_paths.py +0 -0
  179. {codecin-6.2.2 → codecin-6.3.1}/script/gen_isa_docs.py +0 -0
  180. {codecin-6.2.2 → codecin-6.3.1}/script/gen_native_isa.py +0 -0
  181. {codecin-6.2.2 → codecin-6.3.1}/setup.cfg +0 -0
  182. {codecin-6.2.2 → codecin-6.3.1}/setup.py +0 -0
  183. {codecin-6.2.2 → codecin-6.3.1}/tests/test_aggregate_and_const.py +0 -0
  184. {codecin-6.2.2 → codecin-6.3.1}/tests/test_all_libs_together.py +0 -0
  185. {codecin-6.2.2 → codecin-6.3.1}/tests/test_aot.py +0 -0
  186. {codecin-6.2.2 → codecin-6.3.1}/tests/test_assembler_ext.py +0 -0
  187. {codecin-6.2.2 → codecin-6.3.1}/tests/test_bin_compat.py +0 -0
  188. {codecin-6.2.2 → codecin-6.3.1}/tests/test_cin_host.py +0 -0
  189. {codecin-6.2.2 → codecin-6.3.1}/tests/test_cin_host_ext.py +0 -0
  190. {codecin-6.2.2 → codecin-6.3.1}/tests/test_cin_new_features.py +0 -0
  191. {codecin-6.2.2 → codecin-6.3.1}/tests/test_cin_syntax.py +0 -0
  192. {codecin-6.2.2 → codecin-6.3.1}/tests/test_cin_syntax_ext.py +0 -0
  193. {codecin-6.2.2 → codecin-6.3.1}/tests/test_cin_system.py +0 -0
  194. {codecin-6.2.2 → codecin-6.3.1}/tests/test_cli.py +0 -0
  195. {codecin-6.2.2 → codecin-6.3.1}/tests/test_compiler_errors.py +0 -0
  196. {codecin-6.2.2 → codecin-6.3.1}/tests/test_environment.py +0 -0
  197. {codecin-6.2.2 → codecin-6.3.1}/tests/test_examples.py +0 -0
  198. {codecin-6.2.2 → codecin-6.3.1}/tests/test_features_ab.py +0 -0
  199. {codecin-6.2.2 → codecin-6.3.1}/tests/test_features_import.py +0 -0
  200. {codecin-6.2.2 → codecin-6.3.1}/tests/test_features_importloc.py +0 -0
  201. {codecin-6.2.2 → codecin-6.3.1}/tests/test_ffi_net.py +0 -0
  202. {codecin-6.2.2 → codecin-6.3.1}/tests/test_gui.py +0 -0
  203. {codecin-6.2.2 → codecin-6.3.1}/tests/test_index_subscript_type.py +0 -0
  204. {codecin-6.2.2 → codecin-6.3.1}/tests/test_isa_single_source.py +0 -0
  205. {codecin-6.2.2 → codecin-6.3.1}/tests/test_issue_regress.py +0 -0
  206. {codecin-6.2.2 → codecin-6.3.1}/tests/test_keyboard.py +0 -0
  207. {codecin-6.2.2 → codecin-6.3.1}/tests/test_lib_bigint.py +0 -0
  208. {codecin-6.2.2 → codecin-6.3.1}/tests/test_lib_bitset.py +0 -0
  209. {codecin-6.2.2 → codecin-6.3.1}/tests/test_lib_codec.py +0 -0
  210. {codecin-6.2.2 → codecin-6.3.1}/tests/test_lib_combin.py +0 -0
  211. {codecin-6.2.2 → codecin-6.3.1}/tests/test_lib_compat.py +0 -0
  212. {codecin-6.2.2 → codecin-6.3.1}/tests/test_lib_csv.py +0 -0
  213. {codecin-6.2.2 → codecin-6.3.1}/tests/test_lib_dp.py +0 -0
  214. {codecin-6.2.2 → codecin-6.3.1}/tests/test_lib_fmt.py +0 -0
  215. {codecin-6.2.2 → codecin-6.3.1}/tests/test_lib_frac.py +0 -0
  216. {codecin-6.2.2 → codecin-6.3.1}/tests/test_lib_graph.py +0 -0
  217. {codecin-6.2.2 → codecin-6.3.1}/tests/test_lib_heap.py +0 -0
  218. {codecin-6.2.2 → codecin-6.3.1}/tests/test_lib_path.py +0 -0
  219. {codecin-6.2.2 → codecin-6.3.1}/tests/test_lib_set.py +0 -0
  220. {codecin-6.2.2 → codecin-6.3.1}/tests/test_lib_text.py +0 -0
  221. {codecin-6.2.2 → codecin-6.3.1}/tests/test_lib_token.py +0 -0
  222. {codecin-6.2.2 → codecin-6.3.1}/tests/test_lib_tree.py +0 -0
  223. {codecin-6.2.2 → codecin-6.3.1}/tests/test_lib_unionfind.py +0 -0
  224. {codecin-6.2.2 → codecin-6.3.1}/tests/test_libs.py +0 -0
  225. {codecin-6.2.2 → codecin-6.3.1}/tests/test_libs_ext.py +0 -0
  226. {codecin-6.2.2 → codecin-6.3.1}/tests/test_literals_and_bom.py +0 -0
  227. {codecin-6.2.2 → codecin-6.3.1}/tests/test_native_codegen.py +0 -0
  228. {codecin-6.2.2 → codecin-6.3.1}/tests/test_native_hardening.py +0 -0
  229. {codecin-6.2.2 → codecin-6.3.1}/tests/test_native_lib_lookup.py +0 -0
  230. {codecin-6.2.2 → codecin-6.3.1}/tests/test_nested_subscript_codegen.py +0 -0
  231. {codecin-6.2.2 → codecin-6.3.1}/tests/test_no_go_cli.py +0 -0
  232. {codecin-6.2.2 → codecin-6.3.1}/tests/test_object_link.py +0 -0
  233. {codecin-6.2.2 → codecin-6.3.1}/tests/test_p0_fixes.py +0 -0
  234. {codecin-6.2.2 → codecin-6.3.1}/tests/test_packaging.py +0 -0
  235. {codecin-6.2.2 → codecin-6.3.1}/tests/test_paths_consistency.py +0 -0
  236. {codecin-6.2.2 → codecin-6.3.1}/tests/test_sparse_memory.py +0 -0
  237. {codecin-6.2.2 → codecin-6.3.1}/tests/test_struct_value_semantics.py +0 -0
  238. {codecin-6.2.2 → codecin-6.3.1}/tests/test_switch_semantics.py +0 -0
  239. {codecin-6.2.2 → codecin-6.3.1}/tests/test_v620_cvm.py +0 -0
  240. {codecin-6.2.2 → codecin-6.3.1}/tests/test_v620_import.py +0 -0
  241. {codecin-6.2.2 → codecin-6.3.1}/tests/test_v620_mkn.py +0 -0
  242. {codecin-6.2.2 → codecin-6.3.1}/tests/test_v620_packaging.py +0 -0
  243. {codecin-6.2.2 → codecin-6.3.1}/tests/test_v620_pic.py +0 -0
  244. {codecin-6.2.2 → codecin-6.3.1}/tests/test_v620_pic_git.py +0 -0
  245. {codecin-6.2.2 → codecin-6.3.1}/tests/test_v620_pic_registry.py +0 -0
  246. {codecin-6.2.2 → codecin-6.3.1}/tests/test_version.py +0 -0
  247. {codecin-6.2.2 → codecin-6.3.1}/tests/test_workflows.py +0 -0
@@ -5,6 +5,48 @@
5
5
 
6
6
  ---
7
7
 
8
+ ## [6.3.1] - 2026-10-25
9
+
10
+ 一次以「终端缓存与实时输出」为主题的小版本:新增终端缓存技术,启动/编译期间
11
+ 提前键入的内容不再丢失,程序输出在执行过程中即可实时呈现,终端交互与动态特效
12
+ 更加生动流畅;同时保留完整输出缓存,管道 / 重定向 / 测试捕获行为保持不变。
13
+
14
+ ### 新增 (Added)
15
+
16
+ #### 终端缓存技术
17
+
18
+ - **输入缓存 (type-ahead)**:键盘监听 / 交互式行输入首次激活时,不再清空
19
+ 终端里尚未被读取的残留输入,而是读入统一的键码队列 —— 用户在程序启动、
20
+ 编译期间提前键入的字符不会丢失,`get_key` / `key_wait` / `input` /
21
+ `input_str` 可直接消费。
22
+ - Windows 端同时跳过鼠标、窗口、焦点与 key-up 事件继续读取,避免队列
23
+ 被非按键事件卡住。
24
+ - 需要主动丢弃旧输入时调用 `key_flush()`:清空键码队列、解码中间态与
25
+ 终端残留输入(Windows `FlushConsoleInputBuffer`,Unix 非阻塞排空)。
26
+ - **输出缓存**:实时输出模式下,程序输出在逐条写往终端的同时仍完整保留在
27
+ 执行结果中(`Result.Output`),新增 `streamed` 标记告知宿主"已实时显示、
28
+ 不要重复打印";API 调用方与测试仍可读取完整输出。
29
+ - **运行前状态实时显示**:真实终端下依次输出 `Loading <文件> ...` →
30
+ `Loaded N instructions in X ms` → `Running ...`,编译/装载阶段不再黑屏
31
+ 等待;`--log-level ERROR` 与管道输出保持干净。
32
+ - **演示程序**:新增 `examples/terminal_cache_demo.cin`,覆盖打字机/旋转指示器/
33
+ 进度条实时动画、动画期间提前输入的文字与原始键码读取,以及 `key_flush()`
34
+ 显式清理;直接运行 `codecin examples/terminal_cache_demo.cin` 即可体验。
35
+
36
+ ### 变更 (Changed)
37
+
38
+ - **执行与输出时效性优化**:Python CLI 与 AOT 产物(VM 后端及生成的原生
39
+ 后端)在真实终端下改为边执行边写标准输出,`print` / 终端绘制类特效不再
40
+ 等整个程序结束后一次性出现;管道 / 重定向 / 测试捕获仍保持"缓冲 + 结束
41
+ 回传",输出字节与旧版本完全一致。
42
+ - **原生 ABI 扩展**:`codecin_run_v2` 的 `flags` 新增 bit1 = 实时输出请求;
43
+ 结果缓冲 36 字节头中 `offset 2` 由保留字节改为 `streamed` 标志(`offset 3`
44
+ 仍为保留字节),布局与长度不变。
45
+ - 版本号提升至 **6.3.1**(`codecin/__init__.py` 单一真源,
46
+ `codecin/native/engine/version_gen.go` 同步)。
47
+
48
+ ---
49
+
8
50
  ## [6.2.2] - 2026-10-24
9
51
 
10
52
  一次以「注册服务与输入设备」为主题的小版本:`registry` 服务端由 Go 迁移到
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codecin
3
- Version: 6.2.2
3
+ Version: 6.3.1
4
4
  Summary: Code CIN - 高级语言与运行时 (CIN/PL/ASM 工具链 + Go 原生 VM + ARM64/RISC-V/FP/Vector 指令集)
5
5
  Author: ByUsi Studio, 北啊呢
6
6
  License-Expression: MIT
@@ -76,12 +76,10 @@ cvm env
76
76
  安装后的包无需修改源码即可导入:
77
77
 
78
78
  ```cin
79
- import "hello" // 包入口 (pic.toml 的 entry)
80
- import "hello/util.cin" // 包内文件
79
+ import "hello"
80
+ import "hello/util.cin"
81
81
  ```
82
82
 
83
- 完整设计、格式与验收标准见 [V6.2.0-PLAN.md](V6.2.0-PLAN.md)。
84
-
85
83
  ## 文档
86
84
 
87
85
  **官方文档站**位于独立仓库
@@ -58,12 +58,10 @@ cvm env
58
58
  安装后的包无需修改源码即可导入:
59
59
 
60
60
  ```cin
61
- import "hello" // 包入口 (pic.toml 的 entry)
62
- import "hello/util.cin" // 包内文件
61
+ import "hello"
62
+ import "hello/util.cin"
63
63
  ```
64
64
 
65
- 完整设计、格式与验收标准见 [V6.2.0-PLAN.md](V6.2.0-PLAN.md)。
66
-
67
65
  ## 文档
68
66
 
69
67
  **官方文档站**位于独立仓库
@@ -1,4 +1,4 @@
1
- __version__ = "6.2.2"
1
+ __version__ = "6.3.1"
2
2
  __author__ = "ByUsi Studio"
3
3
 
4
4
  from .config import Config
@@ -8,6 +8,7 @@ import argparse
8
8
  import contextlib
9
9
  import os
10
10
  import sys
11
+ import time
11
12
  from typing import List, Optional
12
13
 
13
14
  from . import __version__
@@ -36,6 +37,14 @@ HELP_INTRO = f"""{Colors.colorize(f'Code CIN v{__version__}', Colors.CYAN, True)
36
37
  """
37
38
 
38
39
 
40
+ def _stdout_is_tty() -> bool:
41
+ """stdout 是否为真实终端 (仅此时打印运行前进度状态)。"""
42
+ try:
43
+ return bool(sys.stdout is not None and sys.stdout.isatty())
44
+ except (OSError, ValueError, AttributeError):
45
+ return False
46
+
47
+
39
48
  def build_parser() -> argparse.ArgumentParser:
40
49
  """参数表单一来源 (与 Config 字段一一对应)。"""
41
50
  p = argparse.ArgumentParser(
@@ -446,6 +455,13 @@ def main(argv: Optional[List[str]] = None) -> int:
446
455
  if ns.build_exe is not None:
447
456
  return _run_aot_build(ns, console, program_file, config)
448
457
 
458
+ # 运行前进度/状态只在真实终端且未静音 (log-level ERROR) 时显示,
459
+ # 管道/重定向与"保持示例输出干净"的场景不受影响。
460
+ tty = _stdout_is_tty() and config.log_level.upper() not in ('ERROR', 'CRITICAL')
461
+ if tty:
462
+ console.print(Colors.colorize(
463
+ f"Loading {os.path.basename(program_file)} ...", Colors.CYAN))
464
+ load_started = time.perf_counter()
449
465
  try:
450
466
  from .cpu import CPU
451
467
  cpu = CPU(config, program_file, crom_file=crom_file)
@@ -460,6 +476,12 @@ def main(argv: Optional[List[str]] = None) -> int:
460
476
  console.print_exception()
461
477
  return 1
462
478
 
479
+ if tty:
480
+ console.print(Colors.colorize(
481
+ f"Loaded {len(cpu.instructions)} instructions in "
482
+ f"{(time.perf_counter() - load_started) * 1000:.1f} ms",
483
+ Colors.GREEN))
484
+
463
485
  try:
464
486
  # 管道/重定向输入预读到 input_buffer: 让 input() 在原生与解释器路径下
465
487
  # 都能读到 `"42" | codecin t.cin` 这样的标准输入 (交互 TTY 不预读)。
@@ -477,6 +499,9 @@ def main(argv: Optional[List[str]] = None) -> int:
477
499
  if config.compile_only:
478
500
  return 0
479
501
 
502
+ if tty:
503
+ console.print(Colors.colorize("Running ...", Colors.CYAN))
504
+ sys.stdout.flush() # 状态行先落盘, 程序实时输出紧随其后
480
505
  cpu.run()
481
506
  except KeyboardInterrupt:
482
507
  pass
@@ -33,6 +33,14 @@ NATIVE_HINT = (
33
33
  "或 codecin/native/build.sh (Linux/Termux/macOS), 然后重试。")
34
34
 
35
35
 
36
+ def _stdout_is_tty() -> bool:
37
+ """stdout 是否为真实终端 (决定是否请求实时输出)。"""
38
+ try:
39
+ return bool(sys.stdout is not None and sys.stdout.isatty())
40
+ except (OSError, ValueError, AttributeError):
41
+ return False
42
+
43
+
36
44
  class CPU:
37
45
  def __init__(self, config, filename: Optional[str] = None,
38
46
  crom_file: Optional[str] = None,
@@ -184,6 +192,13 @@ class CPU:
184
192
  bytecode = encode_program(self.instructions, self.entry_pc, all_labels)
185
193
  segments = self.memory.snapshot_segments()
186
194
  import time as _time
195
+ # 真实终端 + 非捕获模式: 请求原生引擎边执行边输出 (输出缓存仍会回传)。
196
+ stream = (not self._capture_output) and _stdout_is_tty()
197
+ if stream:
198
+ try:
199
+ sys.stdout.flush() # 先落盘 Python 侧日志, 保证输出顺序
200
+ except (OSError, ValueError):
201
+ pass
187
202
  t0 = _time.perf_counter()
188
203
  result = engine.run_v2(
189
204
  bytecode=bytecode,
@@ -197,6 +212,7 @@ class CPU:
197
212
  args=list(self.config.program_args),
198
213
  seed=self.config.seed,
199
214
  sandbox=self.config.sandbox_mode,
215
+ stream_output=stream,
200
216
  )
201
217
  elapsed = _time.perf_counter() - t0
202
218
  if result is None:
@@ -211,7 +227,11 @@ class CPU:
211
227
 
212
228
  self._apply_native_state(result)
213
229
  if result.get('output'):
214
- self._emit_text(result['output'])
230
+ if result.get('streamed'):
231
+ # 终端已实时显示; 这里只把完整输出放进缓存供调用方读取
232
+ self.output_buffer.append(result['output'])
233
+ else:
234
+ self._emit_text(result['output'])
215
235
  if result.get('error'):
216
236
  raise ExecutionError(result['error'])
217
237
  return False
@@ -54,13 +54,17 @@ func Main(bytecode, segFile []byte) int {
54
54
  MemSize: int64(memSize),
55
55
  Input: in,
56
56
  MaxSteps: maxSteps,
57
+ // AOT 产物在真实终端下边跑边输出; 管道/重定向保持结束一次性打印。
58
+ StreamOutput: true,
57
59
  })
58
60
  if res == nil {
59
61
  fmt.Fprintln(os.Stderr, "runtime error: no result")
60
62
  return 1
61
63
  }
62
64
  engine.ConsoleInit()
63
- fmt.Print(res.Output)
65
+ if !res.Streamed { // 实时模式下输出已写到终端, Output 只是缓存
66
+ fmt.Print(res.Output)
67
+ }
64
68
  if res.Status == engine.StatusError ||
65
69
  res.Status == engine.StatusUnsupported {
66
70
  msg := res.ErrMsg
@@ -80,12 +80,17 @@ var keyOutSink = func(s string) {
80
80
  }
81
81
 
82
82
  // keyEnsure 惰性启用键盘监听; 可重复调用 (恢复后再次调用会重新启用)。
83
- // 返回是否"本次调用刚激活" (真实终端首次启用), 供 VM 切换直写输出。
83
+ // 返回是否"本次调用刚激活" (真实终端首次启用), 供 VM 切换实时输出。
84
+ // 激活时把终端里已经键入、尚未被程序读取的字符读入队列 (type-ahead 缓存),
85
+ // 不丢弃 —— 用户在程序启动/编译期间敲下的输入不会丢失。
84
86
  func keyEnsure() bool {
85
87
  keyMu.Lock()
86
88
  defer keyMu.Unlock()
87
89
  if !keyReady && !keyForcedOff {
88
90
  keyReady = keyEnablePlatform()
91
+ if keyReady {
92
+ keyDrainLocked()
93
+ }
89
94
  return keyReady
90
95
  }
91
96
  return false
@@ -155,6 +160,7 @@ func (vm *vmState) keyGet() uint64 {
155
160
  }
156
161
 
157
162
  // keyFlush SYS 118: key_flush() 清空键码队列与解码中间态 -> 0
163
+ // 同时丢弃终端里尚未读取的输入缓存, 避免下一次轮询又把旧键读回来。
158
164
  func (vm *vmState) keyFlush() uint64 {
159
165
  if keyEnsure() {
160
166
  vm.enterDirectOut()
@@ -168,6 +174,9 @@ func (vm *vmState) keyFlush() uint64 {
168
174
  keyU8N = 0
169
175
  keyU8Acc = 0
170
176
  keyResetPlatform()
177
+ if keyReady {
178
+ keyFlushPlatform()
179
+ }
171
180
  return 0
172
181
  }
173
182
 
@@ -31,15 +31,7 @@ func keyEnablePlatform() bool {
31
31
  if ttyIoctl(ttySetAttr, &raw) != nil {
32
32
  return false
33
33
  }
34
- // 清空激活前残留的输入缓存 (如启动命令时敲下的回车)。
35
- // 已是非阻塞 (VMIN=0/VTIME=0): read 无输入时立即返回 0, 不会卡住。
36
- var b [64]byte
37
- for {
38
- n, err := syscall.Read(0, b[:])
39
- if n <= 0 || err != nil {
40
- break
41
- }
42
- }
34
+
43
35
  return true
44
36
  }
45
37
 
@@ -53,6 +45,18 @@ func keyRestorePlatform() {
53
45
  // keyResetPlatform 重置平台侧解码中间态 (key_flush 调用; Unix 无)。
54
46
  func keyResetPlatform() {}
55
47
 
48
+ // keyFlushPlatform 丢弃内核输入队列里尚未读取的字节 (key_flush)。
49
+ // 仅在 raw 模式 (VMIN=0/VTIME=0) 下调用, read 无输入时立即返回 0。
50
+ func keyFlushPlatform() {
51
+ var b [64]byte
52
+ for {
53
+ n, err := syscall.Read(0, b[:])
54
+ if n <= 0 || err != nil {
55
+ break
56
+ }
57
+ }
58
+ }
59
+
56
60
  // keyNext 非阻塞读 stdin 并经转义序列状态机解码。
57
61
  func keyNext() (uint64, bool) {
58
62
  for {
@@ -11,4 +11,7 @@ func keyRestorePlatform() {}
11
11
  // keyResetPlatform 重置平台侧解码中间态 (key_flush 调用; stub 无)。
12
12
  func keyResetPlatform() {}
13
13
 
14
+ // keyFlushPlatform 丢弃平台侧残留输入 (stub 无)。
15
+ func keyFlushPlatform() {}
16
+
14
17
  func keyNext() (uint64, bool) { return 0, false }
@@ -178,8 +178,8 @@ func TestKeyHitAndDrainGuard(t *testing.T) {
178
178
  }
179
179
  }
180
180
 
181
- // TestEnterDirectOutStreamsBuffer 直写模式: 激活时先落盘已缓冲输出,
182
- // 之后 outWrite 逐条直写且不进缓冲 (Result.Output 保持为空, 不双打)。
181
+ // TestEnterDirectOutStreamsBuffer 实时输出模式: 激活时先把已缓冲输出落盘,
182
+ // 之后 outWrite 逐条直写, 同时缓冲保留完整缓存 (Result.Output 仍可读取)。
183
183
  func TestEnterDirectOutStreamsBuffer(t *testing.T) {
184
184
  resetKeyState()
185
185
  defer resetKeyState()
@@ -191,21 +191,21 @@ func TestEnterDirectOutStreamsBuffer(t *testing.T) {
191
191
  vm := newHostVM(4096)
192
192
  vm.outWrite("A")
193
193
  if vm.out.String() != "A" {
194
- t.Fatalf("直写激活前输出应留在缓冲, 实际 %q", vm.out.String())
194
+ t.Fatalf("实时输出激活前输出应留在缓冲, 实际 %q", vm.out.String())
195
195
  }
196
196
  vm.enterDirectOut()
197
197
  if len(got) != 1 || got[0] != "A" {
198
198
  t.Fatalf("激活时应把已缓冲输出落盘, 实际 %v", got)
199
199
  }
200
- if vm.out.Len() != 0 || !vm.outDirect {
201
- t.Fatal("激活后缓冲应清空且置直写标志")
200
+ if vm.out.String() != "A" || !vm.outDirect {
201
+ t.Fatalf("激活后应保留输出缓存且置实时标志, 实际 %q", vm.out.String())
202
202
  }
203
203
  vm.outWrite("B")
204
204
  if len(got) != 2 || got[1] != "B" {
205
205
  t.Fatalf("激活后输出应逐条直写, 实际 %v", got)
206
206
  }
207
- if vm.out.Len() != 0 {
208
- t.Fatalf("直写模式下不应再进缓冲, 实际 %q", vm.out.String())
207
+ if vm.out.String() != "AB" {
208
+ t.Fatalf("实时模式下仍应缓存完整输出, 实际 %q", vm.out.String())
209
209
  }
210
210
  if vm.outCount != 2 {
211
211
  t.Fatalf("outCount 应累计 2, 实际 %d", vm.outCount)
@@ -52,8 +52,8 @@ var (
52
52
  keySurrogate rune // UTF-16 高代理缓存 (与下一事件低代理组合)
53
53
  )
54
54
 
55
- // keyEnablePlatform 校验 stdin 为真实控制台后启用, 并清空启动前残留的
56
- // 输入缓存 (如启动命令时敲下的回车), 避免程序一激活就吃到旧键。
55
+ // keyEnablePlatform 校验 stdin 为真实控制台后启用。启动前已键入的字符
56
+ // 不再丢弃: keyEnsure 会立即把它们读入键码队列 (终端输入缓存)。
57
57
  func keyEnablePlatform() bool {
58
58
  h := consoleHandle()
59
59
  if h == 0 {
@@ -71,7 +71,6 @@ func keyEnablePlatform() bool {
71
71
  raw |= cmExtendedFlags
72
72
  raw &^= cmQuickEdit
73
73
  _, _, _ = procSetConsoleMode.Call(h, uintptr(raw))
74
- _, _, _ = procFlushInputBuf.Call(h)
75
74
  return true
76
75
  }
77
76
 
@@ -87,6 +86,13 @@ func keyRestorePlatform() {
87
86
  // keyResetPlatform 重置平台侧解码中间态 (key_flush 调用)。
88
87
  func keyResetPlatform() { keySurrogate = 0 }
89
88
 
89
+ // keyFlushPlatform 丢弃控制台输入缓冲里尚未读取的残留事件 (key_flush)。
90
+ func keyFlushPlatform() {
91
+ if h := consoleHandle(); h != 0 {
92
+ _, _, _ = procFlushInputBuf.Call(h)
93
+ }
94
+ }
95
+
90
96
  func consoleHandle() uintptr {
91
97
  h, _, _ := procGetStdHandle.Call(stdInputHandle)
92
98
  return h
@@ -105,27 +111,33 @@ var vkKeycode = map[uint16]uint64{
105
111
  // keyNext 非阻塞取下一个已解码键码 (PeekConsoleInputW 先行探测, 不会阻塞)。
106
112
  // INPUT_RECORD/KEY_EVENT_RECORD 按固定偏移手工解码
107
113
  // (sizeof(INPUT_RECORD)=20; keyDown@4 repeat@8 vk@10 char@14 state@16)。
114
+ // 鼠标/窗口/焦点事件与 key-up 事件直接丢弃并继续读, 直到取到按键或队列为空。
108
115
  func keyNext() (uint64, bool) {
109
116
  h := consoleHandle()
110
117
  if h == 0 {
111
118
  return 0, false
112
119
  }
113
- var buf [20]byte
114
- var n uint32
115
- r, _, _ := procPeekInput.Call(h, uintptr(unsafe.Pointer(&buf[0])), 1,
116
- uintptr(unsafe.Pointer(&n)))
117
- if r == 0 || n == 0 {
118
- return 0, false
119
- }
120
- r, _, _ = procReadInput.Call(h, uintptr(unsafe.Pointer(&buf[0])), 1,
121
- uintptr(unsafe.Pointer(&n)))
122
- if r == 0 || n == 0 {
123
- return 0, false
124
- }
125
- if le16(buf[0:2]) != evtKeyEvent {
126
- return 0, false // 鼠标/窗口/焦点等事件: 已读出并丢弃
120
+ for {
121
+ var buf [20]byte
122
+ var n uint32
123
+ r, _, _ := procPeekInput.Call(h, uintptr(unsafe.Pointer(&buf[0])), 1,
124
+ uintptr(unsafe.Pointer(&n)))
125
+ if r == 0 || n == 0 {
126
+ return 0, false
127
+ }
128
+ r, _, _ = procReadInput.Call(h, uintptr(unsafe.Pointer(&buf[0])), 1,
129
+ uintptr(unsafe.Pointer(&n)))
130
+ if r == 0 || n == 0 {
131
+ return 0, false
132
+ }
133
+ if le16(buf[0:2]) != evtKeyEvent {
134
+ continue // 鼠标/窗口/焦点等事件: 已读出并丢弃
135
+ }
136
+ if code, ok := decodeKeyEvent(buf[4:20]); ok {
137
+ return code, true
138
+ }
139
+ // key-up / 修饰键 / 代理对中间态: 继续读下一个事件
127
140
  }
128
- return decodeKeyEvent(buf[4:20])
129
141
  }
130
142
 
131
143
  func le16(b []byte) uint16 { return uint16(b[0]) | uint16(b[1])<<8 }
@@ -85,6 +85,12 @@ func NewNativeRuntime(memSize, sp, heapBase int64, segments []MemSeg,
85
85
  // SetInput 设置 stdin 重定向数据 (IN 指令使用)。
86
86
  func (r *NativeRuntime) SetInput(data []byte) { r.vm.inData = data }
87
87
 
88
+ // SetStreamOutput 请求实时输出 (AOT 产物): 真实终端下逐条直写 stdout,
89
+ // 同时保留完整缓存 (Finish 不会再打印缓存, 避免重复)。
90
+ func (r *NativeRuntime) SetStreamOutput(on bool) {
91
+ r.vm.outDirect = on && stdoutIsTerminal()
92
+ }
93
+
88
94
  // SetSandbox 打开沙箱宿主调用限制。
89
95
  func (r *NativeRuntime) SetSandbox(on bool) { r.vm.sandbox = on }
90
96
 
@@ -620,7 +626,7 @@ func (r *NativeRuntime) Finish(ok bool) int {
620
626
  r.errMsg = "output limit exceeded (16 MiB)"
621
627
  }
622
628
  }
623
- if r.vm.out.Len() > 0 {
629
+ if r.vm.out.Len() > 0 && !r.vm.outDirect {
624
630
  fmt.Print(r.vm.out.String())
625
631
  }
626
632
  if ok {
@@ -4,4 +4,4 @@
4
4
  package engine
5
5
 
6
6
  // BuildVersion 是 Code CIN 的版本号 (被 codecin_version() 与日志使用)。
7
- const BuildVersion = "6.2.2"
7
+ const BuildVersion = "6.3.1"
@@ -57,7 +57,7 @@ type vmState struct {
57
57
  out strings.Builder
58
58
  outOver bool // 输出超过 maxOutputBytes (截断并置错误)
59
59
  outCount int // 两种模式的累计输出字节 (16 MiB 限额依据)
60
- outDirect bool // 键盘监听激活 (真实终端): 输出直写 stdout, 不进缓冲
60
+ outDirect bool // 实时输出模式: 逐条直写 stdout, 同时保留缓冲 (Result.Output 缓存)
61
61
  sysIdx int
62
62
  rng *rand.Rand
63
63
  inData []byte
@@ -144,10 +144,9 @@ func (vm *vmState) outWrite(s string) {
144
144
  }
145
145
  vm.outCount += len(s)
146
146
  if vm.outDirect {
147
- keyOutSink(s)
148
- return
147
+ keyOutSink(s) // 实时可见
149
148
  }
150
- vm.out.WriteString(s)
149
+ vm.out.WriteString(s) // 同时缓存: 调用方仍可通过 Result.Output 读取完整输出
151
150
  }
152
151
 
153
152
  // outByte 追加单字节输出 (同上限)。
@@ -161,16 +160,15 @@ func (vm *vmState) outByte(b byte) {
161
160
  }
162
161
  vm.outCount++
163
162
  if vm.outDirect {
164
- keyOutSink(string(b))
165
- return
163
+ keyOutSink(string(b)) // 实时可见
166
164
  }
167
- vm.out.WriteByte(b)
165
+ vm.out.WriteByte(b) // 同时缓存
168
166
  }
169
167
 
170
- // enterDirectOut 键盘监听激活时切换直写模式: 先把已缓冲输出落到终端
171
- // (激活前的提示先显示), 之后输出逐条直写 stdout, 不再等程序结束一次性回传。
172
- // 非终端 (管道/测试捕获) 永远不会激活, 不会走到这里。
173
- // 激活后 vm.out 恒空 -> Result.Output 为空 -> Python 侧不再打印 (不双打)。
168
+ // enterDirectOut 切换到实时输出模式: 先把已缓冲输出落到终端 (激活前的提示
169
+ // 先显示), 之后输出逐条直写 stdout, 不再等程序结束。缓冲保留, 因此
170
+ // Result.Output 仍包含完整输出 (输出缓存), 调用方依据 Streamed 跳过重复打印。
171
+ // 非终端 (管道/测试捕获) 不会主动切换; 键盘监听激活时也可能走到这里。
174
172
  func (vm *vmState) enterDirectOut() {
175
173
  if vm.outDirect {
176
174
  return
@@ -178,7 +176,6 @@ func (vm *vmState) enterDirectOut() {
178
176
  vm.outDirect = true
179
177
  if vm.out.Len() > 0 {
180
178
  keyOutSink(vm.out.String())
181
- vm.out.Reset()
182
179
  }
183
180
  }
184
181
 
@@ -199,6 +196,7 @@ type Result struct {
199
196
  Vec [32][4]float64
200
197
  Flags struct{ N, Z, C, V bool }
201
198
  Output string
199
+ Streamed bool // 输出已实时写到终端 (Output 仅为缓存, 调用方不要再打印)
202
200
  ErrMsg string
203
201
  Segments []MemSeg // 脏页合并段 (稀疏内存回传)
204
202
  MemSize int64
@@ -216,6 +214,9 @@ type RunOptions struct {
216
214
  MaxSteps int64
217
215
  Sandbox bool // 沙箱: 屏蔽宿主能力系统调用
218
216
  Seed int64 // 随机种子; 0 = 时间随机
217
+ // StreamOutput 请求实时输出: 真实终端下边执行边写 stdout,
218
+ // 同时保留完整输出缓存 (Result.Output)。非终端忽略此请求。
219
+ StreamOutput bool
219
220
  }
220
221
 
221
222
  func decodeBytecode(bc []byte) ([]instruction, int, bool) {
@@ -318,6 +319,8 @@ func RunV2(opts *RunOptions) *Result {
318
319
  if opts.Seed != 0 {
319
320
  vm.rng.Seed(opts.Seed)
320
321
  }
322
+ // 真实终端才启用实时输出; 管道/重定向/测试捕获保持"结束一次性回传"。
323
+ vm.outDirect = opts.StreamOutput && stdoutIsTerminal()
321
324
  vm.dirtyBits = make([]uint64,
322
325
  (uint64(memSize)+(1<<(dirtyPageShift+6))-1)>>(dirtyPageShift+6))
323
326
  // 初始段视为已写内容: 数据段通常会被改写, 直接并入脏位图, 免去逐字节 touch。
@@ -341,16 +344,17 @@ func RunV2(opts *RunOptions) *Result {
341
344
  }
342
345
  }
343
346
  r := &Result{
344
- Status: status,
345
- Pc: vm.pc,
346
- Sp: vm.sp,
347
- HeapPtr: vm.heapPtr,
348
- Steps: vm.steps,
349
- Regs: vm.regs,
350
- Vec: vm.vec,
351
- Output: vm.out.String(),
352
- ErrMsg: errMsg,
353
- MemSize: memSize,
347
+ Status: status,
348
+ Pc: vm.pc,
349
+ Sp: vm.sp,
350
+ HeapPtr: vm.heapPtr,
351
+ Steps: vm.steps,
352
+ Regs: vm.regs,
353
+ Vec: vm.vec,
354
+ Output: vm.out.String(),
355
+ Streamed: vm.outDirect,
356
+ ErrMsg: errMsg,
357
+ MemSize: memSize,
354
358
  }
355
359
  r.Flags.N, r.Flags.Z, r.Flags.C, r.Flags.V = vm.flags.N, vm.flags.Z, vm.flags.C, vm.flags.V
356
360
  r.Segments = vm.dirtySegments()
@@ -1055,14 +1059,15 @@ func (vm *vmState) prepareQueryInput() {
1055
1059
  // flushOut 在阻塞读标准输入前, 把已缓冲输出冲刷到真实终端。
1056
1060
  // 仅在 stdout 为终端时生效 (交互提示可见); 管道/重定向/测试捕获保持
1057
1061
  // 纯缓冲语义 —— 输出仍随 Result.Output 一次性回传, 字节序列不变。
1058
- // 冲刷后 vm.out 清空, 回传结果里不再包含这部分 (不重复打印)。
1062
+ // 冲刷后保持实时模式且不清空缓存: 后续输出继续直写, Result.Output 仍是
1063
+ // 完整缓存 (Result.Streamed=true, Python 侧据此不重复打印)。
1059
1064
  func (vm *vmState) flushOut() {
1060
1065
  if vm.outDirect || vm.out.Len() == 0 || !stdoutIsTerminal() {
1061
1066
  return
1062
1067
  }
1063
1068
  consoleInit()
1064
1069
  keyOutSink(vm.out.String())
1065
- vm.out.Reset()
1070
+ vm.outDirect = true
1066
1071
  }
1067
1072
 
1068
1073
  // ---------------- SYS ----------------
@@ -25,7 +25,7 @@ import (
25
25
  // err_len u16 | err ...
26
26
 
27
27
  // v2 结果缓冲布局 (与 codecin/native.py _parse_result_v2 严格一致):
28
- // status u8 | NZCV 标志 u8 (bit0=N bit1=Z bit2=C bit3=V) | 2B pad
28
+ // status u8 | NZCV 标志 u8 (bit0=N bit1=Z bit2=C bit3=V) | streamed u8 | pad u8
29
29
  // pc u64 sp u64 heap_ptr u64 steps u64
30
30
  // regs 33×u64
31
31
  // vec 32×4×f64
@@ -158,6 +158,7 @@ func marshalResultV2(res *engine.Result) unsafe.Pointer {
158
158
 
159
159
  var status byte
160
160
  var flg byte
161
+ var streamed byte
161
162
  pc, sp, heap, steps := uint64(0), uint64(0), uint64(0), uint64(0)
162
163
  var regs [33]uint64
163
164
  var vec [32][4]float64
@@ -184,6 +185,9 @@ func marshalResultV2(res *engine.Result) unsafe.Pointer {
184
185
  if res.Flags.V {
185
186
  flg |= 8
186
187
  }
188
+ if res.Streamed {
189
+ streamed = 1
190
+ }
187
191
  }
188
192
 
189
193
  segsBytes := 0
@@ -195,6 +199,7 @@ func marshalResultV2(res *engine.Result) unsafe.Pointer {
195
199
 
196
200
  buf[0] = status
197
201
  buf[1] = flg
202
+ buf[2] = streamed
198
203
  pos := 4
199
204
  binary.LittleEndian.PutUint64(buf[pos:], pc)
200
205
  binary.LittleEndian.PutUint64(buf[pos+8:], sp)
@@ -276,13 +281,14 @@ func codecin_run_v2(reqPtr unsafe.Pointer, reqLen C.int,
276
281
  }
277
282
 
278
283
  opts := &engine.RunOptions{
279
- Entry: int64(entry),
280
- SP: int64(sp),
281
- HeapBase: int64(heapBase),
282
- MemSize: int64(memSize),
283
- MaxSteps: int64(maxSteps),
284
- Seed: int64(seed),
285
- Sandbox: flags&1 != 0,
284
+ Entry: int64(entry),
285
+ SP: int64(sp),
286
+ HeapBase: int64(heapBase),
287
+ MemSize: int64(memSize),
288
+ MaxSteps: int64(maxSteps),
289
+ Seed: int64(seed),
290
+ Sandbox: flags&1 != 0,
291
+ StreamOutput: flags&2 != 0,
286
292
  }
287
293
  pos := 0
288
294
  bcLen := readU32(&pos)