main.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. #include <filesystem>
  2. #include <fstream>
  3. #include <iostream>
  4. #include <sstream>
  5. #if __has_include("pocketpy_c.h")
  6. #include "pocketpy_c.h"
  7. #else
  8. // for amalgamated build
  9. #include "pocketpy.h"
  10. #endif
  11. #ifdef _WIN32
  12. #include <windows.h>
  13. std::string pkpy_platform_getline(bool* eof) {
  14. HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
  15. std::wstringstream wss;
  16. WCHAR buf;
  17. DWORD read;
  18. while (ReadConsoleW(hStdin, &buf, 1, &read, NULL) && buf != L'\n') {
  19. if (eof && buf == L'\x1A') *eof = true; // Ctrl+Z
  20. wss << buf;
  21. }
  22. std::wstring wideInput = wss.str();
  23. int length =
  24. WideCharToMultiByte(CP_UTF8, 0, wideInput.c_str(),
  25. (int)wideInput.length(), NULL, 0, NULL, NULL);
  26. std::string output;
  27. output.resize(length);
  28. WideCharToMultiByte(CP_UTF8, 0, wideInput.c_str(), (int)wideInput.length(),
  29. &output[0], length, NULL, NULL);
  30. if (!output.empty() && output.back() == '\r') output.pop_back();
  31. return output;
  32. }
  33. #else
  34. std::string pkpy_platform_getline(bool* eof) {
  35. std::string output;
  36. if (!std::getline(std::cin, output)) {
  37. if (eof) *eof = true;
  38. }
  39. return output;
  40. }
  41. #endif
  42. static int f_input(pkpy_vm* vm) {
  43. if (!pkpy_is_none(vm, -1)) {
  44. pkpy_CString prompt;
  45. bool ok = pkpy_to_string(vm, -1, &prompt);
  46. if (!ok) return 0;
  47. std::cout << prompt << std::flush;
  48. }
  49. bool eof;
  50. std::string output = pkpy_platform_getline(&eof);
  51. pkpy_push_string(vm, pkpy_string(output.c_str()));
  52. return 1;
  53. }
  54. int main(int argc, char** argv) {
  55. #if _WIN32
  56. SetConsoleCP(CP_UTF8);
  57. SetConsoleOutputCP(CP_UTF8);
  58. #endif
  59. pkpy_vm* vm = pkpy_new_vm(true);
  60. pkpy_push_function(vm, "input(prompt=None) -> str", f_input);
  61. pkpy_py_import(vm, "builtins");
  62. pkpy_setattr(vm, pkpy_name("input"));
  63. if (argc == 1) {
  64. void* repl = pkpy_new_repl(vm);
  65. bool need_more_lines = false;
  66. while (true) {
  67. std::cout << (need_more_lines ? "... " : ">>> ");
  68. bool eof = false;
  69. std::string line = pkpy_platform_getline(&eof);
  70. if (eof) break;
  71. need_more_lines = pkpy_repl_input(repl, line.c_str());
  72. }
  73. pkpy_delete_vm(vm);
  74. return 0;
  75. }
  76. if (argc == 2) {
  77. std::string argv_1 = argv[1];
  78. if (argv_1 == "-h" || argv_1 == "--help") goto __HELP;
  79. std::filesystem::path filepath(argv[1]);
  80. filepath = std::filesystem::absolute(filepath);
  81. if (!std::filesystem::exists(filepath)) {
  82. std::cerr << "File not found: " << argv_1 << std::endl;
  83. return 2;
  84. }
  85. std::ifstream file(filepath);
  86. if (!file.is_open()) {
  87. std::cerr << "Failed to open file: " << argv_1 << std::endl;
  88. return 3;
  89. }
  90. std::string src((std::istreambuf_iterator<char>(file)),
  91. std::istreambuf_iterator<char>());
  92. file.close();
  93. pkpy_set_main_argv(vm, argc, argv);
  94. bool ok = pkpy_exec_2(vm, src.c_str(),
  95. filepath.filename().string().c_str(), 0, NULL);
  96. if (!ok) pkpy_clear_error(vm, NULL);
  97. pkpy_delete_vm(vm);
  98. return ok ? 0 : 1;
  99. }
  100. __HELP:
  101. std::cout << "Usage: pocketpy [filename]" << std::endl;
  102. return 0;
  103. }