mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-23 13:00:17 +00:00
up
This commit is contained in:
parent
af9f2ba6c4
commit
051560279d
@ -3,7 +3,7 @@ with open("src/opcodes.h", "rt", encoding='utf-8') as f:
|
|||||||
|
|
||||||
pipeline = [
|
pipeline = [
|
||||||
["hash_table8.hpp", "common.h", "memory.h", "str.h", "safestl.h", "builtins.h", "error.h"],
|
["hash_table8.hpp", "common.h", "memory.h", "str.h", "safestl.h", "builtins.h", "error.h"],
|
||||||
["obj.h", "parser.h", "ref.h", "codeobject.h"],
|
["obj.h", "parser.h", "ref.h", "codeobject.h", "frame.h"],
|
||||||
["vm.h", "compiler.h", "repl.h"],
|
["vm.h", "compiler.h", "repl.h"],
|
||||||
["iter.h", "pocketpy.h"]
|
["iter.h", "pocketpy.h"]
|
||||||
]
|
]
|
||||||
|
@ -51,10 +51,12 @@ def sum(iterable):
|
|||||||
return res
|
return res
|
||||||
|
|
||||||
def map(f, iterable):
|
def map(f, iterable):
|
||||||
return [f(i) for i in iterable]
|
for i in iterable:
|
||||||
|
yield f(i)
|
||||||
|
|
||||||
def zip(a, b):
|
def zip(a, b):
|
||||||
return [(a[i], b[i]) for i in range(min(len(a), len(b)))]
|
for i in range(min(len(a), len(b))):
|
||||||
|
yield (a[i], b[i])
|
||||||
|
|
||||||
def reversed(iterable):
|
def reversed(iterable):
|
||||||
a = list(iterable)
|
a = list(iterable)
|
||||||
@ -136,15 +138,6 @@ def __qsort(a: list, i: int, j: int):
|
|||||||
__qsort(a, d1, i-1)
|
__qsort(a, d1, i-1)
|
||||||
__qsort(a, i+1, d2)
|
__qsort(a, i+1, d2)
|
||||||
|
|
||||||
def __list4reverse(self):
|
|
||||||
i, j = 0, len(self)-1
|
|
||||||
while i < j:
|
|
||||||
self[i], self[j] = self[j], self[i]
|
|
||||||
i += 1
|
|
||||||
j -= 1
|
|
||||||
list.reverse = __list4reverse
|
|
||||||
del __list4reverse
|
|
||||||
|
|
||||||
def __list4sort(self, reverse=False):
|
def __list4sort(self, reverse=False):
|
||||||
__qsort(self, 0, len(self)-1)
|
__qsort(self, 0, len(self)-1)
|
||||||
if reverse:
|
if reverse:
|
||||||
|
143
src/codeobject.h
143
src/codeobject.h
@ -107,146 +107,3 @@ struct CodeObject {
|
|||||||
}
|
}
|
||||||
/************************************************/
|
/************************************************/
|
||||||
};
|
};
|
||||||
|
|
||||||
static THREAD_LOCAL i64 kFrameGlobalId = 0;
|
|
||||||
|
|
||||||
struct Frame {
|
|
||||||
std::vector<PyVar> _data;
|
|
||||||
int _ip = -1;
|
|
||||||
int _next_ip = 0;
|
|
||||||
|
|
||||||
const CodeObject_ co;
|
|
||||||
PyVar _module;
|
|
||||||
pkpy::shared_ptr<pkpy::NameDict> _locals;
|
|
||||||
const i64 id;
|
|
||||||
std::stack<std::pair<int, std::vector<PyVar>>> s_try_block;
|
|
||||||
|
|
||||||
inline pkpy::NameDict& f_locals() noexcept { return *_locals; }
|
|
||||||
inline pkpy::NameDict& f_globals() noexcept { return _module->attr(); }
|
|
||||||
|
|
||||||
Frame(const CodeObject_ co, PyVar _module, pkpy::shared_ptr<pkpy::NameDict> _locals)
|
|
||||||
: co(co), _module(_module), _locals(_locals), id(kFrameGlobalId++) { }
|
|
||||||
|
|
||||||
inline const Bytecode& next_bytecode() {
|
|
||||||
_ip = _next_ip++;
|
|
||||||
return co->codes[_ip];
|
|
||||||
}
|
|
||||||
|
|
||||||
Str snapshot(){
|
|
||||||
int line = co->codes[_ip].line;
|
|
||||||
return co->src->snapshot(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Str stack_info(){
|
|
||||||
// StrStream ss;
|
|
||||||
// ss << "[";
|
|
||||||
// for(int i=0; i<_data.size(); i++){
|
|
||||||
// ss << OBJ_TP_NAME(_data[i]);
|
|
||||||
// if(i != _data.size()-1) ss << ", ";
|
|
||||||
// }
|
|
||||||
// ss << "]";
|
|
||||||
// return ss.str();
|
|
||||||
// }
|
|
||||||
|
|
||||||
inline bool has_next_bytecode() const {
|
|
||||||
return _next_ip < co->codes.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline PyVar pop(){
|
|
||||||
if(_data.empty()) throw std::runtime_error("_data.empty() is true");
|
|
||||||
PyVar v = std::move(_data.back());
|
|
||||||
_data.pop_back();
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void _pop(){
|
|
||||||
if(_data.empty()) throw std::runtime_error("_data.empty() is true");
|
|
||||||
_data.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void try_deref(VM*, PyVar&);
|
|
||||||
|
|
||||||
inline PyVar pop_value(VM* vm){
|
|
||||||
PyVar value = pop();
|
|
||||||
try_deref(vm, value);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline PyVar top_value(VM* vm){
|
|
||||||
PyVar value = top();
|
|
||||||
try_deref(vm, value);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline PyVar& top(){
|
|
||||||
if(_data.empty()) throw std::runtime_error("_data.empty() is true");
|
|
||||||
return _data.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline PyVar top_value_offset(VM* vm, int n){
|
|
||||||
PyVar value = _data[_data.size() + n];
|
|
||||||
try_deref(vm, value);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline void push(T&& obj){ _data.push_back(std::forward<T>(obj)); }
|
|
||||||
|
|
||||||
inline void jump_abs(int i){ _next_ip = i; }
|
|
||||||
inline void jump_rel(int i){ _next_ip += i; }
|
|
||||||
|
|
||||||
inline void on_try_block_enter(){
|
|
||||||
s_try_block.push(std::make_pair(co->codes[_ip].block, _data));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void on_try_block_exit(){
|
|
||||||
s_try_block.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool jump_to_exception_handler(){
|
|
||||||
if(s_try_block.empty()) return false;
|
|
||||||
PyVar obj = pop();
|
|
||||||
auto& p = s_try_block.top();
|
|
||||||
_data = std::move(p.second);
|
|
||||||
_data.push_back(obj);
|
|
||||||
_next_ip = co->blocks[p.first].end;
|
|
||||||
on_try_block_exit();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void jump_abs_safe(int target){
|
|
||||||
const Bytecode& prev = co->codes[_ip];
|
|
||||||
int i = prev.block;
|
|
||||||
_next_ip = target;
|
|
||||||
if(_next_ip >= co->codes.size()){
|
|
||||||
while(i>=0){
|
|
||||||
if(co->blocks[i].type == FOR_LOOP) pop();
|
|
||||||
else if(co->blocks[i].type == TRY_EXCEPT) on_try_block_exit();
|
|
||||||
i = co->blocks[i].parent;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
const Bytecode& next = co->codes[target];
|
|
||||||
while(i>=0 && i!=next.block){
|
|
||||||
if(co->blocks[i].type == FOR_LOOP) pop();
|
|
||||||
else if(co->blocks[i].type == TRY_EXCEPT) on_try_block_exit();
|
|
||||||
i = co->blocks[i].parent;
|
|
||||||
}
|
|
||||||
if(i!=next.block) throw std::runtime_error("invalid jump");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pkpy::Args pop_n_values_reversed(VM* vm, int n){
|
|
||||||
pkpy::Args v(n);
|
|
||||||
for(int i=n-1; i>=0; i--){
|
|
||||||
v[i] = pop();
|
|
||||||
try_deref(vm, v[i]);
|
|
||||||
}
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
pkpy::Args pop_n_reversed(int n){
|
|
||||||
pkpy::Args v(n);
|
|
||||||
for(int i=n-1; i>=0; i--) v[i] = pop();
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
};
|
|
144
src/frame.h
Normal file
144
src/frame.h
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "codeobject.h"
|
||||||
|
|
||||||
|
static THREAD_LOCAL i64 kFrameGlobalId = 0;
|
||||||
|
|
||||||
|
struct Frame {
|
||||||
|
std::vector<PyVar> _data;
|
||||||
|
int _ip = -1;
|
||||||
|
int _next_ip = 0;
|
||||||
|
|
||||||
|
const CodeObject_ co;
|
||||||
|
PyVar _module;
|
||||||
|
pkpy::shared_ptr<pkpy::NameDict> _locals;
|
||||||
|
const i64 id;
|
||||||
|
std::stack<std::pair<int, std::vector<PyVar>>> s_try_block;
|
||||||
|
|
||||||
|
inline pkpy::NameDict& f_locals() noexcept { return *_locals; }
|
||||||
|
inline pkpy::NameDict& f_globals() noexcept { return _module->attr(); }
|
||||||
|
|
||||||
|
Frame(const CodeObject_ co, PyVar _module, pkpy::shared_ptr<pkpy::NameDict> _locals)
|
||||||
|
: co(co), _module(_module), _locals(_locals), id(kFrameGlobalId++) { }
|
||||||
|
|
||||||
|
inline const Bytecode& next_bytecode() {
|
||||||
|
_ip = _next_ip++;
|
||||||
|
return co->codes[_ip];
|
||||||
|
}
|
||||||
|
|
||||||
|
Str snapshot(){
|
||||||
|
int line = co->codes[_ip].line;
|
||||||
|
return co->src->snapshot(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Str stack_info(){
|
||||||
|
// StrStream ss;
|
||||||
|
// ss << "[";
|
||||||
|
// for(int i=0; i<_data.size(); i++){
|
||||||
|
// ss << OBJ_TP_NAME(_data[i]);
|
||||||
|
// if(i != _data.size()-1) ss << ", ";
|
||||||
|
// }
|
||||||
|
// ss << "]";
|
||||||
|
// return ss.str();
|
||||||
|
// }
|
||||||
|
|
||||||
|
inline bool has_next_bytecode() const {
|
||||||
|
return _next_ip < co->codes.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline PyVar pop(){
|
||||||
|
if(_data.empty()) throw std::runtime_error("_data.empty() is true");
|
||||||
|
PyVar v = std::move(_data.back());
|
||||||
|
_data.pop_back();
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void _pop(){
|
||||||
|
if(_data.empty()) throw std::runtime_error("_data.empty() is true");
|
||||||
|
_data.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void try_deref(VM*, PyVar&);
|
||||||
|
|
||||||
|
inline PyVar pop_value(VM* vm){
|
||||||
|
PyVar value = pop();
|
||||||
|
try_deref(vm, value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline PyVar top_value(VM* vm){
|
||||||
|
PyVar value = top();
|
||||||
|
try_deref(vm, value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline PyVar& top(){
|
||||||
|
if(_data.empty()) throw std::runtime_error("_data.empty() is true");
|
||||||
|
return _data.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline PyVar top_value_offset(VM* vm, int n){
|
||||||
|
PyVar value = _data[_data.size() + n];
|
||||||
|
try_deref(vm, value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline void push(T&& obj){ _data.push_back(std::forward<T>(obj)); }
|
||||||
|
|
||||||
|
inline void jump_abs(int i){ _next_ip = i; }
|
||||||
|
inline void jump_rel(int i){ _next_ip += i; }
|
||||||
|
|
||||||
|
inline void on_try_block_enter(){
|
||||||
|
s_try_block.push(std::make_pair(co->codes[_ip].block, _data));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void on_try_block_exit(){
|
||||||
|
s_try_block.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool jump_to_exception_handler(){
|
||||||
|
if(s_try_block.empty()) return false;
|
||||||
|
PyVar obj = pop();
|
||||||
|
auto& p = s_try_block.top();
|
||||||
|
_data = std::move(p.second);
|
||||||
|
_data.push_back(obj);
|
||||||
|
_next_ip = co->blocks[p.first].end;
|
||||||
|
on_try_block_exit();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _exit_block(int i){
|
||||||
|
if(co->blocks[i].type == FOR_LOOP) pop();
|
||||||
|
else if(co->blocks[i].type == TRY_EXCEPT) on_try_block_exit();
|
||||||
|
return co->blocks[i].parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void jump_abs_safe(int target){
|
||||||
|
const Bytecode& prev = co->codes[_ip];
|
||||||
|
int i = prev.block;
|
||||||
|
_next_ip = target;
|
||||||
|
if(_next_ip >= co->codes.size()){
|
||||||
|
while(i>=0) i = _exit_block(i);
|
||||||
|
}else{
|
||||||
|
const Bytecode& next = co->codes[target];
|
||||||
|
while(i>=0 && i!=next.block) i = _exit_block(i);
|
||||||
|
if(i!=next.block) throw std::runtime_error("invalid jump");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pkpy::Args pop_n_values_reversed(VM* vm, int n){
|
||||||
|
pkpy::Args v(n);
|
||||||
|
for(int i=n-1; i>=0; i--){
|
||||||
|
v[i] = pop();
|
||||||
|
try_deref(vm, v[i]);
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
pkpy::Args pop_n_reversed(int n){
|
||||||
|
pkpy::Args v(n);
|
||||||
|
for(int i=n-1; i>=0; i--) v[i] = pop();
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
};
|
@ -394,6 +394,12 @@ void init_builtins(VM* _vm) {
|
|||||||
return vm->None;
|
return vm->None;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_vm->bind_method<0>("list", "reverse", [](VM* vm, pkpy::Args& args) {
|
||||||
|
pkpy::List& self = vm->PyList_AS_C(args[0]);
|
||||||
|
std::reverse(self.begin(), self.end());
|
||||||
|
return vm->None;
|
||||||
|
});
|
||||||
|
|
||||||
_vm->bind_method<1>("list", "__mul__", [](VM* vm, pkpy::Args& args) {
|
_vm->bind_method<1>("list", "__mul__", [](VM* vm, pkpy::Args& args) {
|
||||||
const pkpy::List& self = vm->PyList_AS_C(args[0]);
|
const pkpy::List& self = vm->PyList_AS_C(args[0]);
|
||||||
int n = (int)vm->PyInt_AS_C(args[1]);
|
int n = (int)vm->PyInt_AS_C(args[1]);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user