diff --git a/amalgamate.py b/amalgamate.py index 121f9d3c..05e2bc6e 100644 --- a/amalgamate.py +++ b/amalgamate.py @@ -3,7 +3,7 @@ with open("src/opcodes.h", "rt", encoding='utf-8') as f: pipeline = [ ["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"], ["iter.h", "pocketpy.h"] ] diff --git a/src/builtins.h b/src/builtins.h index 37d21f3c..01115f9d 100644 --- a/src/builtins.h +++ b/src/builtins.h @@ -51,10 +51,12 @@ def sum(iterable): return res def map(f, iterable): - return [f(i) for i in iterable] + for i in iterable: + yield f(i) 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): a = list(iterable) @@ -136,15 +138,6 @@ def __qsort(a: list, i: int, j: int): __qsort(a, d1, i-1) __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): __qsort(self, 0, len(self)-1) if reverse: diff --git a/src/codeobject.h b/src/codeobject.h index 293a4861..31c9a13e 100644 --- a/src/codeobject.h +++ b/src/codeobject.h @@ -107,146 +107,3 @@ struct CodeObject { } /************************************************/ }; - -static THREAD_LOCAL i64 kFrameGlobalId = 0; - -struct Frame { - std::vector _data; - int _ip = -1; - int _next_ip = 0; - - const CodeObject_ co; - PyVar _module; - pkpy::shared_ptr _locals; - const i64 id; - std::stack>> 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 _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 - inline void push(T&& obj){ _data.push_back(std::forward(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; - } -}; \ No newline at end of file diff --git a/src/frame.h b/src/frame.h new file mode 100644 index 00000000..e82a391a --- /dev/null +++ b/src/frame.h @@ -0,0 +1,144 @@ +#pragma once + +#include "codeobject.h" + +static THREAD_LOCAL i64 kFrameGlobalId = 0; + +struct Frame { + std::vector _data; + int _ip = -1; + int _next_ip = 0; + + const CodeObject_ co; + PyVar _module; + pkpy::shared_ptr _locals; + const i64 id; + std::stack>> 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 _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 + inline void push(T&& obj){ _data.push_back(std::forward(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; + } +}; \ No newline at end of file diff --git a/src/pocketpy.h b/src/pocketpy.h index fd0f3d61..ee361ece 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -394,6 +394,12 @@ void init_builtins(VM* _vm) { 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) { const pkpy::List& self = vm->PyList_AS_C(args[0]); int n = (int)vm->PyInt_AS_C(args[1]); diff --git a/src/vm.h b/src/vm.h index 8b252baa..7428f12c 100644 --- a/src/vm.h +++ b/src/vm.h @@ -1,6 +1,6 @@ #pragma once -#include "codeobject.h" +#include "frame.h" #include "error.h" #define DEF_NATIVE(type, ctype, ptype) \