mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
...
This commit is contained in:
parent
d70b7653f2
commit
f7af705367
@ -521,8 +521,12 @@ __NEXT_STEP:;
|
|||||||
} DISPATCH();
|
} DISPATCH();
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
// // TODO: using "goto" inside with block may cause __exit__ not called
|
// // TODO: using "goto" inside with block may cause __exit__ not called
|
||||||
// TARGET(WITH_ENTER) call(frame->pop_value(this), __enter__, no_arg()); DISPATCH();
|
TARGET(WITH_ENTER)
|
||||||
// TARGET(WITH_EXIT) call(frame->pop_value(this), __exit__, no_arg()); DISPATCH();
|
call_method(POPX(), __enter__);
|
||||||
|
DISPATCH();
|
||||||
|
TARGET(WITH_EXIT)
|
||||||
|
call_method(POPX(), __exit__);
|
||||||
|
DISPATCH();
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
TARGET(ASSERT) {
|
TARGET(ASSERT) {
|
||||||
PyObject* obj = TOP();
|
PyObject* obj = TOP();
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
#if (defined(__ANDROID__) && __ANDROID_API__ <= 22) || defined(__EMSCRIPTEN__)
|
#if (defined(__ANDROID__) && __ANDROID_API__ <= 22) || defined(__EMSCRIPTEN__)
|
||||||
#define PK_ENABLE_FILEIO 0
|
#define PK_ENABLE_FILEIO 0
|
||||||
#else
|
#else
|
||||||
#define PK_ENABLE_FILEIO 0 // TODO: refactor this
|
#define PK_ENABLE_FILEIO 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// This is the maximum number of arguments in a function declaration
|
// This is the maximum number of arguments in a function declaration
|
||||||
|
@ -795,17 +795,16 @@ __SUBSCR_END:
|
|||||||
consume_end_stmt();
|
consume_end_stmt();
|
||||||
} break;
|
} break;
|
||||||
case TK("with"): {
|
case TK("with"): {
|
||||||
// TODO: reimpl this
|
|
||||||
EXPR(false);
|
EXPR(false);
|
||||||
ctx()->emit(OP_POP_TOP, BC_NOARG, prev().line);
|
|
||||||
consume(TK("as"));
|
consume(TK("as"));
|
||||||
consume(TK("@id"));
|
consume(TK("@id"));
|
||||||
// emit(OP_STORE_NAME, index);
|
StrName name(prev().str());
|
||||||
// emit(OP_LOAD_NAME_REF, index);
|
ctx()->emit(OP_STORE_NAME, name.index, prev().line);
|
||||||
// emit(OP_WITH_ENTER);
|
ctx()->emit(OP_LOAD_NAME, name.index, prev().line);
|
||||||
|
ctx()->emit(OP_WITH_ENTER, BC_NOARG, prev().line);
|
||||||
compile_block_body();
|
compile_block_body();
|
||||||
// emit(OP_LOAD_NAME_REF, index);
|
ctx()->emit(OP_LOAD_NAME, name.index, prev().line);
|
||||||
// emit(OP_WITH_EXIT);
|
ctx()->emit(OP_WITH_EXIT, BC_NOARG, prev().line);
|
||||||
} break;
|
} break;
|
||||||
/*************************************************/
|
/*************************************************/
|
||||||
// TODO: refactor goto/label use special $ syntax
|
// TODO: refactor goto/label use special $ syntax
|
||||||
|
65
src/io.h
65
src/io.h
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "ceval.h"
|
#include "ceval.h"
|
||||||
#include "cffi.h"
|
#include "cffi.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
#if PK_ENABLE_FILEIO
|
#if PK_ENABLE_FILEIO
|
||||||
|
|
||||||
@ -11,7 +12,7 @@
|
|||||||
namespace pkpy{
|
namespace pkpy{
|
||||||
|
|
||||||
inline Str _read_file_cwd(const Str& name, bool* ok){
|
inline Str _read_file_cwd(const Str& name, bool* ok){
|
||||||
std::filesystem::path path(name.c_str());
|
std::filesystem::path path(name.sv());
|
||||||
bool exists = std::filesystem::exists(path);
|
bool exists = std::filesystem::exists(path);
|
||||||
if(!exists){
|
if(!exists){
|
||||||
*ok = false;
|
*ok = false;
|
||||||
@ -31,13 +32,17 @@ struct FileIO {
|
|||||||
Str mode;
|
Str mode;
|
||||||
std::fstream _fs;
|
std::fstream _fs;
|
||||||
|
|
||||||
|
bool is_text() const { return mode != "rb" && mode != "wb" && mode != "ab"; }
|
||||||
|
|
||||||
FileIO(VM* vm, Str file, Str mode): file(file), mode(mode) {
|
FileIO(VM* vm, Str file, Str mode): file(file), mode(mode) {
|
||||||
if(mode == "rt" || mode == "r"){
|
if(mode == "rt" || mode == "r" || mode == "rb"){
|
||||||
_fs.open(file, std::ios::in);
|
_fs.open(file.sv(), std::ios::in);
|
||||||
}else if(mode == "wt" || mode == "w"){
|
}else if(mode == "wt" || mode == "w" || mode == "wb"){
|
||||||
_fs.open(file, std::ios::out);
|
_fs.open(file.sv(), std::ios::out);
|
||||||
}else if(mode == "at" || mode == "a"){
|
}else if(mode == "at" || mode == "a" || mode == "ab"){
|
||||||
_fs.open(file, std::ios::app);
|
_fs.open(file.sv(), std::ios::app);
|
||||||
|
}else{
|
||||||
|
vm->ValueError("invalid mode");
|
||||||
}
|
}
|
||||||
if(!_fs.is_open()) vm->IOError(strerror(errno));
|
if(!_fs.is_open()) vm->IOError(strerror(errno));
|
||||||
}
|
}
|
||||||
@ -51,14 +56,19 @@ struct FileIO {
|
|||||||
|
|
||||||
vm->bind_method<0>(type, "read", [](VM* vm, ArgsView args){
|
vm->bind_method<0>(type, "read", [](VM* vm, ArgsView args){
|
||||||
FileIO& io = CAST(FileIO&, args[0]);
|
FileIO& io = CAST(FileIO&, args[0]);
|
||||||
std::string buffer;
|
Bytes buffer;
|
||||||
io._fs >> buffer;
|
io._fs >> buffer._data;
|
||||||
|
if(io.is_text()) return VAR(Str(buffer._data));
|
||||||
return VAR(buffer);
|
return VAR(buffer);
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind_method<1>(type, "write", [](VM* vm, ArgsView args){
|
vm->bind_method<1>(type, "write", [](VM* vm, ArgsView args){
|
||||||
FileIO& io = CAST(FileIO&, args[0]);
|
FileIO& io = CAST(FileIO&, args[0]);
|
||||||
io._fs << CAST(Str&, args[1]);
|
if(io.is_text()) io._fs << CAST(Str&, args[1]);
|
||||||
|
else{
|
||||||
|
Bytes& buffer = CAST(Bytes&, args[1]);
|
||||||
|
io._fs << buffer._data;
|
||||||
|
}
|
||||||
return vm->None;
|
return vm->None;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -80,35 +90,40 @@ struct FileIO {
|
|||||||
|
|
||||||
inline void add_module_io(VM* vm){
|
inline void add_module_io(VM* vm){
|
||||||
PyObject* mod = vm->new_module("io");
|
PyObject* mod = vm->new_module("io");
|
||||||
PyObject* type = FileIO::register_class(vm, mod);
|
FileIO::register_class(vm, mod);
|
||||||
vm->bind_builtin_func<2>("open", [type](VM* vm, ArgsView args){
|
vm->bind_builtin_func<2>("open", [](VM* vm, ArgsView args){
|
||||||
return vm->call(type, args);
|
static StrName m_io("io");
|
||||||
|
static StrName m_FileIO("FileIO");
|
||||||
|
return vm->call(vm->_modules[m_io]->attr(m_FileIO), args[0], args[1]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void add_module_os(VM* vm){
|
inline void add_module_os(VM* vm){
|
||||||
PyObject* mod = vm->new_module("os");
|
PyObject* mod = vm->new_module("os");
|
||||||
|
PyObject* path_obj = vm->heap.gcnew<DummyInstance>(vm->tp_object, {});
|
||||||
|
mod->attr().set("path", path_obj);
|
||||||
|
|
||||||
// Working directory is shared by all VMs!!
|
// Working directory is shared by all VMs!!
|
||||||
vm->bind_func<0>(mod, "getcwd", [](VM* vm, ArgsView args){
|
vm->bind_func<0>(mod, "getcwd", [](VM* vm, ArgsView args){
|
||||||
return VAR(std::filesystem::current_path().string());
|
return VAR(std::filesystem::current_path().string());
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind_func<1>(mod, "chdir", [](VM* vm, ArgsView args){
|
vm->bind_func<1>(mod, "chdir", [](VM* vm, ArgsView args){
|
||||||
std::filesystem::path path(CAST(Str&, args[0]).c_str());
|
std::filesystem::path path(CAST(Str&, args[0]).sv());
|
||||||
std::filesystem::current_path(path);
|
std::filesystem::current_path(path);
|
||||||
return vm->None;
|
return vm->None;
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind_func<1>(mod, "listdir", [](VM* vm, ArgsView args){
|
vm->bind_func<1>(mod, "listdir", [](VM* vm, ArgsView args){
|
||||||
std::filesystem::path path(CAST(Str&, args[0]).c_str());
|
std::filesystem::path path(CAST(Str&, args[0]).sv());
|
||||||
std::filesystem::directory_iterator di;
|
std::filesystem::directory_iterator di;
|
||||||
try{
|
try{
|
||||||
di = std::filesystem::directory_iterator(path);
|
di = std::filesystem::directory_iterator(path);
|
||||||
}catch(std::filesystem::filesystem_error& e){
|
}catch(std::filesystem::filesystem_error& e){
|
||||||
Str msg = e.what();
|
std::string msg = e.what();
|
||||||
auto pos = msg.find_last_of(":");
|
auto pos = msg.find_last_of(":");
|
||||||
if(pos != Str::npos) msg = msg.substr(pos + 1);
|
if(pos != std::string::npos) msg = msg.substr(pos + 1);
|
||||||
vm->IOError(msg.lstrip());
|
vm->IOError(Str(msg).lstrip());
|
||||||
}
|
}
|
||||||
List ret;
|
List ret;
|
||||||
for(auto& p: di) ret.push_back(VAR(p.path().filename().string()));
|
for(auto& p: di) ret.push_back(VAR(p.path().filename().string()));
|
||||||
@ -116,36 +131,36 @@ inline void add_module_os(VM* vm){
|
|||||||
});
|
});
|
||||||
|
|
||||||
vm->bind_func<1>(mod, "remove", [](VM* vm, ArgsView args){
|
vm->bind_func<1>(mod, "remove", [](VM* vm, ArgsView args){
|
||||||
std::filesystem::path path(CAST(Str&, args[0]).c_str());
|
std::filesystem::path path(CAST(Str&, args[0]).sv());
|
||||||
bool ok = std::filesystem::remove(path);
|
bool ok = std::filesystem::remove(path);
|
||||||
if(!ok) vm->IOError("operation failed");
|
if(!ok) vm->IOError("operation failed");
|
||||||
return vm->None;
|
return vm->None;
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind_func<1>(mod, "mkdir", [](VM* vm, ArgsView args){
|
vm->bind_func<1>(mod, "mkdir", [](VM* vm, ArgsView args){
|
||||||
std::filesystem::path path(CAST(Str&, args[0]).c_str());
|
std::filesystem::path path(CAST(Str&, args[0]).sv());
|
||||||
bool ok = std::filesystem::create_directory(path);
|
bool ok = std::filesystem::create_directory(path);
|
||||||
if(!ok) vm->IOError("operation failed");
|
if(!ok) vm->IOError("operation failed");
|
||||||
return vm->None;
|
return vm->None;
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind_func<1>(mod, "rmdir", [](VM* vm, ArgsView args){
|
vm->bind_func<1>(mod, "rmdir", [](VM* vm, ArgsView args){
|
||||||
std::filesystem::path path(CAST(Str&, args[0]).c_str());
|
std::filesystem::path path(CAST(Str&, args[0]).sv());
|
||||||
bool ok = std::filesystem::remove(path);
|
bool ok = std::filesystem::remove(path);
|
||||||
if(!ok) vm->IOError("operation failed");
|
if(!ok) vm->IOError("operation failed");
|
||||||
return vm->None;
|
return vm->None;
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind_func<-1>(mod, "path_join", [](VM* vm, ArgsView args){
|
vm->bind_func<-1>(path_obj, "join", [](VM* vm, ArgsView args){
|
||||||
std::filesystem::path path;
|
std::filesystem::path path;
|
||||||
for(int i=0; i<args.size(); i++){
|
for(int i=0; i<args.size(); i++){
|
||||||
path /= CAST(Str&, args[i]).c_str();
|
path /= CAST(Str&, args[i]).sv();
|
||||||
}
|
}
|
||||||
return VAR(path.string());
|
return VAR(path.string());
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind_func<1>(mod, "path_exists", [](VM* vm, ArgsView args){
|
vm->bind_func<1>(path_obj, "exists", [](VM* vm, ArgsView args){
|
||||||
std::filesystem::path path(CAST(Str&, args[0]).c_str());
|
std::filesystem::path path(CAST(Str&, args[0]).sv());
|
||||||
bool exists = std::filesystem::exists(path);
|
bool exists = std::filesystem::exists(path);
|
||||||
return VAR(exists);
|
return VAR(exists);
|
||||||
});
|
});
|
||||||
|
@ -62,6 +62,9 @@ struct Bytes{
|
|||||||
|
|
||||||
int size() const noexcept { return _data.size(); }
|
int size() const noexcept { return _data.size(); }
|
||||||
int operator[](int i) const noexcept { return (int)(uint8_t)_data[i]; }
|
int operator[](int i) const noexcept { return (int)(uint8_t)_data[i]; }
|
||||||
|
|
||||||
|
bool operator==(const Bytes& rhs) const noexcept { return _data == rhs._data; }
|
||||||
|
bool operator!=(const Bytes& rhs) const noexcept { return _data != rhs._data; }
|
||||||
};
|
};
|
||||||
|
|
||||||
using Super = std::pair<PyObject*, Type>;
|
using Super = std::pair<PyObject*, Type>;
|
||||||
|
@ -102,8 +102,8 @@ OPCODE(BEGIN_CLASS)
|
|||||||
OPCODE(END_CLASS)
|
OPCODE(END_CLASS)
|
||||||
OPCODE(STORE_CLASS_ATTR)
|
OPCODE(STORE_CLASS_ATTR)
|
||||||
/**************************/
|
/**************************/
|
||||||
// OPCODE(WITH_ENTER)
|
OPCODE(WITH_ENTER)
|
||||||
// OPCODE(WITH_EXIT)
|
OPCODE(WITH_EXIT)
|
||||||
/**************************/
|
/**************************/
|
||||||
OPCODE(ASSERT)
|
OPCODE(ASSERT)
|
||||||
OPCODE(EXCEPTION_MATCH)
|
OPCODE(EXCEPTION_MATCH)
|
||||||
|
@ -353,15 +353,15 @@ inline void init_builtins(VM* _vm) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind_method<1>("str", "__eq__", [](VM* vm, ArgsView args) {
|
_vm->bind_method<1>("str", "__eq__", [](VM* vm, ArgsView args) {
|
||||||
if(is_type(args[0], vm->tp_str) && is_type(args[1], vm->tp_str))
|
const Str& self = CAST(Str&, args[0]);
|
||||||
return VAR(CAST(Str&, args[0]) == CAST(Str&, args[1]));
|
if(!is_type(args[1], vm->tp_str)) return VAR(false);
|
||||||
return VAR(args[0] == args[1]);
|
return VAR(self == CAST(Str&, args[1]));
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind_method<1>("str", "__ne__", [](VM* vm, ArgsView args) {
|
_vm->bind_method<1>("str", "__ne__", [](VM* vm, ArgsView args) {
|
||||||
if(is_type(args[0], vm->tp_str) && is_type(args[1], vm->tp_str))
|
const Str& self = CAST(Str&, args[0]);
|
||||||
return VAR(CAST(Str&, args[0]) != CAST(Str&, args[1]));
|
if(!is_type(args[1], vm->tp_str)) return VAR(true);
|
||||||
return VAR(args[0] != args[1]);
|
return VAR(self != CAST(Str&, args[1]));
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind_method<1>("str", "__getitem__", [](VM* vm, ArgsView args) {
|
_vm->bind_method<1>("str", "__getitem__", [](VM* vm, ArgsView args) {
|
||||||
@ -609,6 +609,19 @@ inline void init_builtins(VM* _vm) {
|
|||||||
return VAR(Str(self._data));
|
return VAR(Str(self._data));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_vm->bind_method<1>("bytes", "__eq__", [](VM* vm, ArgsView args) {
|
||||||
|
const Bytes& self = CAST(Bytes&, args[0]);
|
||||||
|
if(!is_type(args[1], vm->tp_bytes)) return VAR(false);
|
||||||
|
const Bytes& other = CAST(Bytes&, args[1]);
|
||||||
|
return VAR(self == other);
|
||||||
|
});
|
||||||
|
|
||||||
|
_vm->bind_method<1>("bytes", "__ne__", [](VM* vm, ArgsView args) {
|
||||||
|
const Bytes& self = CAST(Bytes&, args[0]);
|
||||||
|
if(!is_type(args[1], vm->tp_bytes)) return VAR(true);
|
||||||
|
const Bytes& other = CAST(Bytes&, args[1]);
|
||||||
|
return VAR(self != other);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -18,6 +18,20 @@ with open('123.txt', 'a') as f:
|
|||||||
with open('123.txt', 'r') as f:
|
with open('123.txt', 'r') as f:
|
||||||
assert f.read() == '123456' + '测试'
|
assert f.read() == '123456' + '测试'
|
||||||
|
|
||||||
assert os.path_exists('123.txt')
|
assert os.path.exists('123.txt')
|
||||||
os.remove('123.txt')
|
os.remove('123.txt')
|
||||||
assert not os.path_exists('123.txt')
|
assert not os.path.exists('123.txt')
|
||||||
|
|
||||||
|
|
||||||
|
with open('123.bin', 'wb') as f:
|
||||||
|
f.write('123'.encode())
|
||||||
|
f.write('测试'.encode())
|
||||||
|
|
||||||
|
with open('123.bin', 'rb') as f:
|
||||||
|
b = f.read()
|
||||||
|
assert isinstance(b, bytes)
|
||||||
|
assert b == '123测试'.encode()
|
||||||
|
|
||||||
|
assert os.path.exists('123.bin')
|
||||||
|
os.remove('123.bin')
|
||||||
|
assert not os.path.exists('123.bin')
|
Loading…
x
Reference in New Issue
Block a user