pocketpy/src/repl.h
2023-05-28 18:19:23 +08:00

90 lines
2.4 KiB
C++

#pragma once
#include "compiler.h"
#include "ceval.h"
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#endif
namespace pkpy{
#ifdef _WIN32
inline std::string getline(bool* eof=nullptr) {
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
std::wstringstream wss;
WCHAR buf;
DWORD read;
while (ReadConsoleW(hStdin, &buf, 1, &read, NULL) && buf != L'\n') {
if(eof && buf == L'\x1A') *eof = true; // Ctrl+Z
wss << buf;
}
std::wstring wideInput = wss.str();
int length = WideCharToMultiByte(CP_UTF8, 0, wideInput.c_str(), (int)wideInput.length(), NULL, 0, NULL, NULL);
std::string output;
output.resize(length);
WideCharToMultiByte(CP_UTF8, 0, wideInput.c_str(), (int)wideInput.length(), &output[0], length, NULL, NULL);
if(!output.empty() && output.back() == '\r') output.pop_back();
return output;
}
#else
inline std::string getline(bool* eof=nullptr){
std::string line;
if(!std::getline(std::cin, line)){
if(eof) *eof = true;
}
return line;
}
#endif
class REPL {
protected:
int need_more_lines = 0;
std::string buffer;
VM* vm;
public:
REPL(VM* vm) : vm(vm){
vm->_stdout(vm, "pocketpy " PK_VERSION " (" __DATE__ ", " __TIME__ ") ");
vm->_stdout(vm, fmt("[", sizeof(void*)*8, " bit]" "\n"));
vm->_stdout(vm, "https://github.com/blueloveTH/pocketpy" "\n");
vm->_stdout(vm, "Type \"exit()\" to exit." "\n");
}
bool input(std::string line){
CompileMode mode = REPL_MODE;
if(need_more_lines){
buffer += line;
buffer += '\n';
int n = buffer.size();
if(n>=need_more_lines){
for(int i=buffer.size()-need_more_lines; i<buffer.size(); i++){
// no enough lines
if(buffer[i] != '\n') return true;
}
need_more_lines = 0;
line = buffer;
buffer.clear();
mode = CELL_MODE;
}else{
return true;
}
}
try{
vm->exec(line, "<stdin>", mode);
}catch(NeedMoreLines& ne){
buffer += line;
buffer += '\n';
need_more_lines = ne.is_compiling_class ? 3 : 2;
if (need_more_lines) return true;
}
return false;
}
};
} // namespace pkpy