├── .gitignore ├── CMakeLists.txt ├── README.md ├── code ├── binaryFileParser.cpp ├── binaryFileParser.hpp ├── bytecode.hpp ├── codeObject.cpp └── codeObject.hpp ├── extlib └── math.cpp ├── inc └── koshox.hpp ├── lib └── builtin.py ├── main.cpp ├── memory ├── heap.cpp ├── heap.hpp ├── oopClosure.cpp └── oopClosure.hpp ├── object ├── hiDict.cpp ├── hiDict.hpp ├── hiInteger.cpp ├── hiInteger.hpp ├── hiList.cpp ├── hiList.hpp ├── hiObject.cpp ├── hiObject.hpp ├── hiString.cpp ├── hiString.hpp ├── klass.cpp └── klass.hpp ├── runtime ├── cellObject.cpp ├── cellObject.hpp ├── frameObject.cpp ├── frameObject.hpp ├── functionObject.cpp ├── functionObject.hpp ├── generator.cpp ├── generator.hpp ├── interpreter.cpp ├── interpreter.hpp ├── module.cpp ├── module.hpp ├── stringTable.cpp ├── stringTable.hpp ├── traceback.cpp ├── traceback.hpp ├── universe.cpp └── universe.hpp ├── test ├── class1.py ├── closure.py ├── constructor.py ├── decorator.py ├── dict.py ├── dict2.py ├── dict_iterator.py ├── extends.py ├── func.py ├── func_bound.py ├── func_def.py ├── func_default_param.py ├── hello_if.py ├── hello_while.py ├── key_arg.py ├── list.py ├── list_append.py ├── list_contains.py ├── list_insert.py ├── list_iterator.py ├── list_modify.py ├── list_plus.py ├── list_sort.py ├── list_subscr.py ├── method.py ├── native_func.py ├── none.py ├── object_instance.py ├── object_prop.py ├── op_overload1.py ├── op_overload2.py ├── op_overload3.py ├── op_overload4.py ├── op_overload5.py ├── test_break.py ├── test_builtin_lib.py ├── test_continue.py ├── test_coroutine.py ├── test_exception.py ├── test_exception_trace.py ├── test_finally.py ├── test_func.py ├── test_gc1.py ├── test_generator.py ├── test_global.py ├── test_global2.py ├── test_import.py ├── test_iter_fib.py ├── test_param.py ├── test_so.py ├── type_object.py └── type_prop.py └── util ├── arrayList.cpp ├── arrayList.hpp ├── bufferedInputStream.hpp ├── handles.cpp ├── handles.hpp ├── map.cpp ├── map.hpp ├── stack.cpp └── stack.hpp /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | cmake-build-debug/ 3 | *.pyc 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | project(pythonvm) 3 | 4 | SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -Wall -g -ggdb") 5 | SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -Wall") 6 | 7 | INCLUDE_DIRECTORIES(./) 8 | 9 | ADD_EXECUTABLE(pythonvm main.cpp) 10 | 11 | set(SOURCE_FILE 12 | object/hiInteger.cpp 13 | object/hiString.cpp 14 | object/hiObject.cpp 15 | object/hiList.cpp 16 | object/hiDict.cpp 17 | object/klass.cpp 18 | util/arrayList.cpp 19 | util/map.cpp 20 | util/handles.cpp 21 | runtime/interpreter.cpp 22 | runtime/universe.cpp 23 | runtime/frameObject.cpp 24 | runtime/functionObject.cpp 25 | runtime/stringTable.cpp 26 | runtime/module.cpp 27 | runtime/traceback.cpp 28 | runtime/generator.cpp 29 | runtime/cellObject.cpp 30 | memory/heap.cpp 31 | memory/oopClosure.cpp 32 | code/binaryFileParser.cpp 33 | code/codeObject.cpp) 34 | 35 | ADD_LIBRARY(pyvm SHARED ${SOURCE_FILE}) 36 | 37 | ADD_LIBRARY(math SHARED extlib/math.cpp) 38 | 39 | ADD_CUSTOM_COMMAND(TARGET math 40 | POST_BUILD 41 | COMMAND mkdir -p lib 42 | COMMAND cp libmath.dll lib/ 43 | COMMAND cp ../lib/*.py lib/ 44 | COMMAND python2 -m compileall lib/*.py 45 | ) 46 | 47 | TARGET_LINK_LIBRARIES(pyvm -ldl) 48 | TARGET_LINK_LIBRARIES(math pyvm) 49 | 50 | TARGET_LINK_LIBRARIES(pythonvm pyvm ${CMAKE_DL_LIBS}) 51 | 52 | set_target_properties(pyvm PROPERTIES PREFIX "lib") 53 | set_target_properties(math PROPERTIES PREFIX "lib") -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 自己动手写Python虚拟机 2 | 3 | [《自己动手写Python虚拟机》](https://book.douban.com/subject/34442805/)源码 4 | 5 | ### 开发环境 6 | 7 | win10 + cygwin + clion 8 | 9 | ### 主要功能 10 | 11 | 1. 基本实现了书上所有的功能,从零构建一个简单的Python虚拟机。 12 | 13 | 2. 除了GC还存在一些问题,需要参考作者的新项目HiLang改造为链表记录对象的创建。 14 | 15 | 3. 对随书源码的几个小问题做了修改,CMakeLists也做了一点调整。 16 | 17 | 18 | 19 | 最后一章实现了yield和generator以后,就可以写出一个最简单的协程: 20 | 21 | ```python 22 | # Two simple generator functions 23 | def countdown(n): 24 | while n > 0: 25 | print('T-minus', n) 26 | yield 27 | n -= 1 28 | print('Blastoff!') 29 | 30 | 31 | def countup(n): 32 | x = 0 33 | while x < n: 34 | print('Counting up', x) 35 | yield 36 | x += 1 37 | 38 | 39 | class TaskScheduler: 40 | def __init__(self): 41 | self._task_queue = [] 42 | 43 | def new_task(self, task): 44 | ''' 45 | Admit a newly started task to the scheduler 46 | ''' 47 | self._task_queue.append(task) 48 | 49 | def run(self): 50 | ''' 51 | Run until there are no more tasks 52 | ''' 53 | while len(self._task_queue) > 0: 54 | task = self._task_queue.popleft() 55 | try: 56 | # Run until the next yield statement 57 | task.next() 58 | self._task_queue.append(task) 59 | except StopIteration: 60 | # Generator is no longer executing 61 | pass 62 | 63 | 64 | # Example use 65 | sched = TaskScheduler() 66 | sched.new_task(countdown(2)) 67 | sched.new_task(countup(5)) 68 | sched.run() 69 | ``` 70 | 71 | 输出结果: 72 | 73 | ```py 74 | [T-minus, 2] 75 | [Counting up, 0] 76 | [T-minus, 1] 77 | [Counting up, 1] 78 | Blastoff! 79 | [Counting up, 2] 80 | [Counting up, 3] 81 | [Counting up, 4] 82 | ``` 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /code/binaryFileParser.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/14. 3 | // 4 | 5 | #include 6 | #include 7 | 8 | #include "runtime/universe.hpp" 9 | #include "util/bufferedInputStream.hpp" 10 | #include "object/hiInteger.hpp" 11 | #include "binaryFileParser.hpp" 12 | #include "object/hiList.hpp" 13 | 14 | BinaryFileParser::BinaryFileParser(BufferedInputStream *stream) { 15 | file_stream = stream; 16 | } 17 | 18 | CodeObject *BinaryFileParser::parse() { 19 | int magic_number = file_stream->read_int(); 20 | printf("magic number is 0x%x\n", magic_number); 21 | 22 | int moddate = file_stream->read_int(); 23 | printf("moddate is 0x%x\n", moddate); 24 | 25 | char object_type = file_stream->read(); 26 | 27 | if (object_type == 'c') { 28 | CodeObject *result = get_code_object(); 29 | printf("parse OK!\n"); 30 | return result; 31 | } 32 | 33 | return NULL; 34 | } 35 | 36 | CodeObject *BinaryFileParser::get_code_object() { 37 | int argcount = file_stream->read_int(); 38 | printf("argcount is 0x%x\n", argcount); 39 | int nlocals = file_stream->read_int(); 40 | int stacksize = file_stream->read_int(); 41 | int flags = file_stream->read_int(); 42 | printf("flags is 0x%x\n", flags); 43 | 44 | HiString *byte_codes = get_byte_codes(); 45 | ArrayList *consts = get_consts(); 46 | ArrayList *names = get_names(); 47 | ArrayList *var_names = get_var_names(); 48 | ArrayList *free_vars = get_free_vars(); 49 | ArrayList *cell_vars = get_cell_vars(); 50 | 51 | HiString *file_name = get_file_name(); 52 | HiString *module_name = get_name(); 53 | int begin_line_no = file_stream->read_int(); 54 | HiString *lnotab = get_no_table(); 55 | 56 | HiString *file_path = new HiString(file_stream->get_file_path()); 57 | 58 | return new CodeObject(argcount, nlocals, stacksize, flags, byte_codes, 59 | consts, names, var_names, free_vars, cell_vars, file_name, module_name, 60 | begin_line_no, lnotab, file_path); 61 | } 62 | 63 | 64 | HiString *BinaryFileParser::get_byte_codes() { 65 | assert(file_stream->read() == 's'); 66 | 67 | return get_string(); 68 | } 69 | 70 | HiString *BinaryFileParser::get_string() { 71 | int length = file_stream->read_int(); 72 | char *str_value = new char[length]; 73 | 74 | for (int i = 0; i < length; i++) { 75 | str_value[i] = file_stream->read(); 76 | } 77 | 78 | HiString *str = new HiString(str_value, length); 79 | delete[] str_value; 80 | 81 | return str; 82 | } 83 | 84 | HiString *BinaryFileParser::get_no_table() { 85 | char ch = file_stream->read(); 86 | 87 | if (ch != 's' && ch != 't') { 88 | file_stream->unread(); 89 | return NULL; 90 | } 91 | 92 | return get_string(); 93 | } 94 | 95 | HiString *BinaryFileParser::get_name() { 96 | char ch = file_stream->read(); 97 | 98 | if (ch == 's') { 99 | return get_string(); 100 | } else if (ch == 't') { 101 | HiString *str = get_string(); 102 | _string_table.add(str); 103 | return str; 104 | } else if (ch == 'R') { 105 | return _string_table.get(file_stream->read_int()); 106 | } 107 | 108 | return NULL; 109 | } 110 | 111 | HiString *BinaryFileParser::get_file_name() { 112 | return get_name(); 113 | } 114 | 115 | ArrayList *BinaryFileParser::get_consts() { 116 | if (file_stream->read() == '(') { 117 | return get_tuple(); 118 | } 119 | 120 | file_stream->unread(); 121 | return NULL; 122 | } 123 | 124 | ArrayList *BinaryFileParser::get_names() { 125 | if (file_stream->read() == '(') { 126 | return get_tuple(); 127 | } 128 | 129 | file_stream->unread(); 130 | return NULL; 131 | } 132 | 133 | ArrayList *BinaryFileParser::get_var_names() { 134 | if (file_stream->read() == '(') { 135 | return get_tuple(); 136 | } 137 | 138 | file_stream->unread(); 139 | return NULL; 140 | } 141 | 142 | ArrayList *BinaryFileParser::get_free_vars() { 143 | if (file_stream->read() == '(') { 144 | return get_tuple(); 145 | } 146 | 147 | file_stream->unread(); 148 | return NULL; 149 | } 150 | 151 | ArrayList *BinaryFileParser::get_cell_vars() { 152 | if (file_stream->read() == '(') { 153 | return get_tuple(); 154 | } 155 | 156 | file_stream->unread(); 157 | return NULL; 158 | } 159 | 160 | ArrayList *BinaryFileParser::get_tuple() { 161 | int length = file_stream->read_int(); 162 | HiString *str; 163 | 164 | ArrayList *list = new ArrayList(length); 165 | for (int i = 0; i < length; ++i) { 166 | char obj_type = file_stream->read(); 167 | 168 | switch (obj_type) { 169 | case 'c': 170 | // CodeObject 171 | printf("got a code object\n"); 172 | list->add(get_code_object()); 173 | break; 174 | case 'i': 175 | // Integer 176 | list->add(new HiInteger(file_stream->read_int())); 177 | break; 178 | case 'N': 179 | list->add(Universe::HiNone); 180 | break; 181 | case 't': 182 | // String 183 | str = get_string(); 184 | list->add(str); 185 | _string_table.add(str); 186 | break; 187 | case 's': 188 | // String 189 | list->add(get_string()); 190 | break; 191 | case 'R': 192 | list->add(_string_table.get(file_stream->read_int())); 193 | break; 194 | case '(': 195 | list->add(new HiList(get_tuple())); 196 | break; 197 | default: 198 | printf("parser, unrecognized type : %c\n", obj_type); 199 | } 200 | } 201 | 202 | return list; 203 | } 204 | 205 | -------------------------------------------------------------------------------- /code/binaryFileParser.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/14. 3 | // 4 | 5 | #ifndef PYTHONVM_BINARYFILEPARSER_HPP 6 | #define PYTHONVM_BINARYFILEPARSER_HPP 7 | 8 | #include "../util/bufferedInputStream.hpp" 9 | #include "../util/arrayList.hpp" 10 | #include "../object/hiString.hpp" 11 | #include "codeObject.hpp" 12 | 13 | class BinaryFileParser { 14 | private: 15 | BufferedInputStream *file_stream; 16 | 17 | int cur; 18 | 19 | ArrayList _string_table; 20 | 21 | public: 22 | BinaryFileParser(BufferedInputStream *stream); 23 | 24 | public: 25 | CodeObject *parse(); 26 | 27 | CodeObject *get_code_object(); 28 | 29 | HiString *get_byte_codes(); 30 | 31 | HiString *get_no_table(); 32 | 33 | HiString *get_string(); 34 | 35 | HiString *get_name(); 36 | 37 | HiString *get_file_name(); 38 | 39 | ArrayList *get_consts(); 40 | 41 | ArrayList *get_names(); 42 | 43 | ArrayList *get_var_names(); 44 | 45 | ArrayList *get_free_vars(); 46 | 47 | ArrayList *get_cell_vars(); 48 | 49 | ArrayList *get_tuple(); 50 | }; 51 | 52 | #endif //PYTHONVM_BINARYFILEPARSER_HPP 53 | -------------------------------------------------------------------------------- /code/bytecode.hpp: -------------------------------------------------------------------------------- 1 | #ifndef BYTE_CODE_HPP 2 | #define BYTE_CODE_HPP 3 | 4 | class ByteCode { 5 | public: 6 | // Define pythonvm.Bytecode Operator Code 7 | static const unsigned char POP_TOP = 1; 8 | static const unsigned char ROT_TWO = 2; 9 | static const unsigned char ROT_THREE = 3; 10 | static const unsigned char DUP_TOP = 4; 11 | static const unsigned char UNARY_NEGATIVE = 11; 12 | static const unsigned char BINARY_MULTIPLY = 20; 13 | static const unsigned char BINARY_MODULO = 22; 14 | static const unsigned char BINARY_SUBSCR = 25; 15 | static const unsigned char BINARY_DIVIDE = 21; 16 | static const unsigned char BINARY_ADD = 23; 17 | static const unsigned char BINARY_SUBTRACT = 24; 18 | 19 | static const unsigned char INPLACE_ADD = 55; 20 | static const unsigned char STORE_MAP = 54; 21 | static const unsigned char INPLACE_SUBSTRACT = 56; 22 | static const unsigned char INPLACE_MULTIPLY = 57; 23 | static const unsigned char INPLACE_DIVIDE = 58; 24 | static const unsigned char INPLACE_MODULO = 59; 25 | static const unsigned char STORE_SUBSCR = 60; 26 | static const unsigned char DELETE_SUBSCR = 61; 27 | 28 | static const unsigned char GET_ITER = 68; 29 | 30 | static const unsigned char PRINT_ITEM = 71; 31 | static const unsigned char PRINT_NEWLINE = 72; 32 | 33 | static const unsigned char BREAK_LOOP = 80; 34 | static const unsigned char LOAD_LOCALS = 82; 35 | static const unsigned char RETURN_VALUE = 83; 36 | static const unsigned char YIELD_VALUE = 86; 37 | static const unsigned char POP_BLOCK = 87; 38 | static const unsigned char END_FINALLY = 88; 39 | static const unsigned char BUILD_CLASS = 89; 40 | 41 | // This is a separator 42 | static const unsigned char HAVE_ARGUMENT = 90; /* Opcodes from here have an argument: */ 43 | 44 | static const unsigned char STORE_NAME = 90; /* Index in name list */ 45 | static const unsigned char UNPACK_SEQUENCE = 92; 46 | static const unsigned char FOR_ITER = 93; 47 | static const unsigned char STORE_ATTR = 95; /* Index in name list */ 48 | static const unsigned char STORE_GLOBAL = 97; 49 | static const unsigned char DUP_TOPX = 99; /* number of items to duplicate */ 50 | static const unsigned char LOAD_CONST = 100; /* Index in const list */ 51 | static const unsigned char LOAD_NAME = 101; /* Index in name list */ 52 | static const unsigned char BUILD_TUPLE = 102; 53 | static const unsigned char BUILD_LIST = 103; 54 | static const unsigned char BUILD_MAP = 105; 55 | static const unsigned char LOAD_ATTR = 106; /* Index in name list */ 56 | static const unsigned char COMPARE_OP = 107; /* Comparison operator */ 57 | static const unsigned char IMPORT_NAME = 108; /* Index in name list */ 58 | static const unsigned char IMPORT_FROM = 109; /* Index in name list */ 59 | static const unsigned char JUMP_FORWARD = 110; /* Number of bytes to skip */ 60 | static const unsigned char JUMP_IF_FALSE_OR_POP = 111; /* Target byte offset from beginning 61 | of code */ 62 | 63 | static const unsigned char JUMP_ABSOLUTE = 113; 64 | static const unsigned char POP_JUMP_IF_FALSE = 114; 65 | static const unsigned char POP_JUMP_IF_TRUE = 115; 66 | static const unsigned char LOAD_GLOBAL = 116; /* Index in name list */ 67 | 68 | static const unsigned char CONTINUE_LOOP = 119; /* Start of loop (absolute) */ 69 | static const unsigned char SETUP_LOOP = 120; /* Target address (relative) */ 70 | static const unsigned char SETUP_EXCEPT = 121; /* "" */ 71 | static const unsigned char SETUP_FINALLY = 122; /* "" */ 72 | 73 | static const unsigned char LOAD_FAST = 124; /* Local variable number */ 74 | static const unsigned char STORE_FAST = 125; /* Local variable number */ 75 | 76 | static const unsigned char RAISE_VARARGS = 130; 77 | static const unsigned char CALL_FUNCTION = 131; 78 | static const unsigned char MAKE_FUNCTION = 132; 79 | 80 | static const unsigned char MAKE_CLOSURE = 134; /* #free vars */ 81 | static const unsigned char LOAD_CLOSURE = 135; /* Load free variable from closure */ 82 | static const unsigned char LOAD_DEREF = 136; /* Load and dereference from closure cell */ 83 | static const unsigned char STORE_DEREF = 137; /* Store into cell */ 84 | 85 | static const unsigned char CALL_FUNCTION_VAR = 140; 86 | 87 | enum COMPARE { 88 | LESS = 0, 89 | LESS_EQUAL, 90 | EQUAL, 91 | NOT_EQUAL, 92 | GREATER, 93 | GREATER_EQUAL, 94 | IN, 95 | NOT_IN, 96 | IS, 97 | IS_NOT, 98 | EXC_MATCH 99 | }; 100 | }; 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /code/codeObject.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/14. 3 | // 4 | 5 | #include "code/codeObject.hpp" 6 | #include "object/hiString.hpp" 7 | #include "memory/heap.hpp" 8 | #include "memory/oopClosure.hpp" 9 | 10 | CodeKlass *CodeKlass::instance = NULL; 11 | 12 | CodeKlass *CodeKlass::get_instance() { 13 | if (instance == NULL) { 14 | instance = new CodeKlass(); 15 | } 16 | 17 | return instance; 18 | } 19 | 20 | 21 | CodeKlass::CodeKlass() { 22 | set_name(new HiString("code")); 23 | add_super(ObjectKlass::get_instance()); 24 | HiTypeObject *dict_type_obj = new HiTypeObject(); 25 | set_type_object(dict_type_obj); 26 | } 27 | 28 | void CodeKlass::oops_do(OopClosure *f, HiObject *obj) { 29 | CodeObject *co = (CodeObject *) obj; 30 | assert(co && co->klass() == (Klass *) this); 31 | 32 | f->do_oop((HiObject **) &co->_bytecodes); 33 | f->do_array_list(&co->_names); 34 | f->do_array_list(&co->_consts); 35 | f->do_array_list(&co->_var_names); 36 | f->do_array_list(&co->_free_vars); 37 | f->do_array_list(&co->_cell_vars); 38 | f->do_oop((HiObject **) &co->_co_name); 39 | f->do_oop((HiObject **) &co->_file_name); 40 | f->do_oop((HiObject **) &co->_notable); 41 | f->do_oop((HiObject **) &co->_file_path); 42 | } 43 | 44 | size_t CodeKlass::size() { 45 | return sizeof(CodeObject); 46 | } 47 | 48 | CodeObject::CodeObject(int argcount, int nlocals, int stacksize, int flag, HiString *bytecodes, 49 | ArrayList *consts, ArrayList *names, ArrayList *varnames, 50 | ArrayList *freevars, ArrayList *cellvars, 51 | HiString *file_name, HiString *co_name, int lineno, HiString *notable, HiString *file_path) : 52 | _argcount(argcount), 53 | _nlocals(nlocals), 54 | _stack_size(stacksize), 55 | _flag(flag), 56 | _bytecodes(bytecodes), 57 | _names(names), 58 | _consts(consts), 59 | _var_names(varnames), 60 | _free_vars(freevars), 61 | _cell_vars(cellvars), 62 | _co_name(co_name), 63 | _file_name(file_name), 64 | _lineno(lineno), 65 | _notable(notable), 66 | _file_path(file_path){ 67 | set_klass(CodeKlass::get_instance()); 68 | } -------------------------------------------------------------------------------- /code/codeObject.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/14. 3 | // 4 | 5 | #ifndef PYTHONVM_CODEOBJECT_HPP 6 | #define PYTHONVM_CODEOBJECT_HPP 7 | 8 | #include "object/hiObject.hpp" 9 | 10 | class HiString; 11 | 12 | template 13 | class ArrayList; 14 | 15 | class CodeKlass : public Klass { 16 | private: 17 | CodeKlass(); 18 | 19 | static CodeKlass *instance; 20 | 21 | public: 22 | static CodeKlass *get_instance(); 23 | 24 | virtual void oops_do(OopClosure *closure, HiObject *obj); 25 | 26 | virtual size_t size(); 27 | }; 28 | 29 | class CodeObject : public HiObject { 30 | public: 31 | int _argcount; 32 | int _nlocals; 33 | int _stack_size; 34 | int _flag; 35 | 36 | HiString *_bytecodes; 37 | ArrayList *_names; 38 | ArrayList *_consts; 39 | ArrayList *_var_names; 40 | 41 | ArrayList *_free_vars; 42 | ArrayList *_cell_vars; // 在本函数定义,被内部函数引用的变量 43 | 44 | HiString *_co_name; 45 | HiString *_file_name; 46 | 47 | int _lineno; 48 | HiString *_notable; 49 | 50 | HiString *_file_path; 51 | 52 | CodeObject(int argcount, int nlocals, int stacksize, int flag, HiString *bytecodes, 53 | ArrayList *consts, ArrayList *names, 54 | ArrayList *varnames, 55 | ArrayList *freevars, ArrayList *cellvars, 56 | HiString *file_name, HiString *co_name, int lineno, HiString *notable, HiString *file_path); 57 | }; 58 | 59 | #endif //PYTHONVM_CODEOBJECT_HPP 60 | -------------------------------------------------------------------------------- /extlib/math.cpp: -------------------------------------------------------------------------------- 1 | #include "inc/koshox.hpp" 2 | 3 | #include 4 | 5 | HiObject *add(ObjList args) { 6 | HiInteger *a = (HiInteger *) args->get(0); 7 | HiInteger *b = (HiInteger *) args->get(1); 8 | 9 | return new HiInteger(a->value() + b->value()); 10 | } 11 | 12 | RGMethod math_methods[] = { 13 | {"add", add, 0, "add two integer",}, 14 | {NULL, NULL, 0, NULL,}, 15 | }; 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | SO_PUBLIC RGMethod *init_libmath() { 22 | return math_methods; 23 | } 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | -------------------------------------------------------------------------------- /inc/koshox.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/10/8. 3 | // 4 | 5 | #ifndef PYTHONVM_KOSHOX_HPP 6 | #define PYTHONVM_KOSHOX_HPP 7 | 8 | #include "runtime/functionObject.hpp" 9 | #include "object/hiInteger.hpp" 10 | 11 | #define SO_PUBLIC __attribute__((visibility("default"))) 12 | 13 | struct RGMethod { 14 | const char *method_name; 15 | NativeFuncPointer method; 16 | int method_info; 17 | const char *method_doc; 18 | }; 19 | 20 | typedef RGMethod* (*INIT_FUNC)(); 21 | 22 | #endif //PYTHONVM_KOSHOX_HPP 23 | -------------------------------------------------------------------------------- /lib/builtin.py: -------------------------------------------------------------------------------- 1 | def map(func, iterable): 2 | l = [] 3 | for i in iterable: 4 | l.append(func(i)) 5 | 6 | return l 7 | 8 | 9 | def filter(func, iterable): 10 | l = [] 11 | for i in iterable: 12 | if func(i): 13 | l.append(i) 14 | 15 | return l 16 | 17 | 18 | def sum(iterable, i): 19 | temp = i 20 | for e in iterable: 21 | temp = temp + e 22 | 23 | return temp 24 | 25 | 26 | def range(*args): 27 | start = 0 28 | step = 1 29 | 30 | if len(args) == 1: 31 | end = args[0] 32 | elif len(args) == 2: 33 | start = args[0] 34 | end = args[1] 35 | else: 36 | start = args[0] 37 | end = args[1] 38 | step = args[2] 39 | 40 | lst = [] 41 | if (start < end and step > 0): 42 | while start < end: 43 | lst.append(start) 44 | start += step 45 | elif (start > end and step < 0): 46 | while start > end: 47 | lst.append(start) 48 | start += step 49 | else: 50 | print "Error" 51 | 52 | return lst 53 | 54 | 55 | class Exception(object): 56 | def __init__(self, *args): 57 | self.info = args 58 | 59 | def __repr__(self): 60 | return " ".join(self.info) 61 | 62 | 63 | class StopIteration(Exception): 64 | pass 65 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "runtime/interpreter.hpp" 3 | #include "runtime/universe.hpp" 4 | #include "util/bufferedInputStream.hpp" 5 | #include "code/binaryFileParser.hpp" 6 | #include "memory/heap.hpp" 7 | 8 | int main(int argc, char **argv) { 9 | if (argc <= 1) { 10 | printf("vm need a param : filename\n"); 11 | return 0; 12 | } 13 | 14 | Universe::genesis(); 15 | BufferedInputStream stream(argv[1]); 16 | BinaryFileParser parser(&stream); 17 | Universe::main_code = parser.parse(); 18 | // TODO Function default GC有问题 19 | // Universe::heap->gc(); 20 | 21 | Interpreter::get_instance()->run(Universe::main_code); 22 | 23 | return 0; 24 | } -------------------------------------------------------------------------------- /memory/heap.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/9/13. 3 | // 4 | #include 5 | #include 6 | 7 | #include "runtime/universe.hpp" 8 | #include "memory/heap.hpp" 9 | #include "memory/oopClosure.hpp" 10 | 11 | Space::Space(size_t size) { 12 | _size = size; 13 | _base = (char *) malloc(size); 14 | _end = _base + size; 15 | _top = (char *) (((long long) (_base + 15)) & -16); // 16字节对齐 16 | _capacity = _end - _top; 17 | } 18 | 19 | Space::~Space() { 20 | if (_base) { 21 | free(_base); 22 | _base = 0; 23 | } 24 | 25 | _top = 0; 26 | _end = 0; 27 | _capacity = 0; 28 | _size = 0; 29 | } 30 | 31 | bool Space::can_alloc(size_t size) { 32 | return _capacity > size; 33 | } 34 | 35 | bool Space::has_obj(char *obj) { 36 | return obj >= _base && _end > obj; 37 | } 38 | 39 | void *Space::allocate(size_t size) { 40 | // 8字节对齐 41 | size = (size + 7) & -8; 42 | char *start = _top; 43 | _top += size; 44 | _capacity -= size; 45 | return start; 46 | } 47 | 48 | void Space::clear() { 49 | memset(_base, 0, _size); 50 | _top = (char *) (((long long) (_base + 15)) & -16); 51 | _capacity = _end - _top; 52 | } 53 | 54 | Heap *Heap::instance = NULL; 55 | size_t Heap::MAX_CAP = 2 * 1024 * 1024; 56 | 57 | Heap *Heap::get_instance() { 58 | if (instance == NULL) 59 | instance = new Heap(MAX_CAP); 60 | 61 | return instance; 62 | } 63 | 64 | Heap::Heap(size_t size) { 65 | mem_1 = new Space(size); 66 | mem_2 = new Space(size); 67 | metaspace = new Space(size / 16); 68 | 69 | mem_1->clear(); 70 | mem_2->clear(); 71 | metaspace->clear(); 72 | 73 | eden = mem_1; 74 | survivor = mem_2; 75 | } 76 | 77 | Heap::~Heap() { 78 | if (mem_1) { 79 | delete mem_1; 80 | mem_1 = NULL; 81 | } 82 | 83 | if (mem_2) { 84 | delete mem_2; 85 | mem_2 = NULL; 86 | } 87 | 88 | if (metaspace) { 89 | delete metaspace; 90 | metaspace = NULL; 91 | } 92 | 93 | eden = NULL; 94 | survivor = NULL; 95 | } 96 | 97 | void *Heap::allocate(size_t size) { 98 | if (!eden->can_alloc(size)) { 99 | gc(); 100 | } 101 | 102 | return eden->allocate(size); 103 | } 104 | 105 | void *Heap::allocate_meta(size_t size) { 106 | if (!metaspace->can_alloc(size)) { 107 | return NULL; 108 | } 109 | 110 | return metaspace->allocate(size); 111 | } 112 | 113 | void Heap::copy_live_objects() { 114 | ScavengeOopClosure* closure = new ScavengeOopClosure(eden, survivor, metaspace); 115 | closure->scavenge(); 116 | delete closure; 117 | } 118 | 119 | void Heap::gc() { 120 | printf("gc starting...\n"); 121 | printf(" befroe gc : \n"); 122 | printf(" eden's capacity is %lu\n", eden->_capacity); 123 | copy_live_objects(); 124 | 125 | Space *temp = eden; 126 | eden = survivor; 127 | survivor = temp; 128 | 129 | printf(" after gc : \n"); 130 | printf(" eden's capacity is %lu\n", eden->_capacity); 131 | printf("gc end\n"); 132 | 133 | survivor->clear(); 134 | } 135 | -------------------------------------------------------------------------------- /memory/heap.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/9/13. 3 | // 4 | 5 | #ifndef PYTHONVM_HEAP_HPP 6 | #define PYTHONVM_HEAP_HPP 7 | 8 | #include 9 | 10 | class HiObject; 11 | 12 | /* base top end 13 | * ↓ ↓ ↓ 14 | * |------------|--capacity--| 15 | * |-----------size----------| 16 | */ 17 | class Space { 18 | friend class Heap; 19 | 20 | private: 21 | char *_base; 22 | char *_top; 23 | char *_end; 24 | size_t _size; 25 | size_t _capacity; 26 | 27 | Space(size_t size); 28 | 29 | ~Space(); 30 | 31 | public: 32 | bool can_alloc(size_t size); 33 | 34 | bool has_obj(char *obj); 35 | 36 | void *allocate(size_t size); 37 | 38 | void clear(); 39 | }; 40 | 41 | class Heap { 42 | private: 43 | Space *mem_1; 44 | Space *mem_2; 45 | 46 | Space *eden; 47 | Space *survivor; 48 | 49 | Space *metaspace; 50 | 51 | Heap(size_t size); 52 | 53 | public: 54 | static size_t MAX_CAP; 55 | static Heap *instance; 56 | static Heap *get_instance(); 57 | 58 | ~Heap(); 59 | 60 | void *allocate(size_t size); 61 | 62 | void *allocate_meta(size_t size); 63 | 64 | void copy_live_objects(); 65 | 66 | void gc(); 67 | }; 68 | 69 | #endif //PYTHONVM_HEAP_HPP 70 | -------------------------------------------------------------------------------- /memory/oopClosure.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/9/18. 3 | // 4 | 5 | #include "runtime/universe.hpp" 6 | #include "runtime/stringTable.hpp" 7 | #include "runtime/interpreter.hpp" 8 | #include "memory/oopClosure.hpp" 9 | #include "memory/heap.hpp" 10 | #include "util/map.hpp" 11 | #include "util/stack.hpp" 12 | #include "object/hiObject.hpp" 13 | 14 | ScavengeOopClosure::ScavengeOopClosure(Space *from, Space *to, Space *meta) { 15 | _from = from; 16 | _to = to; 17 | _meta = meta; 18 | 19 | _oop_stack = new Stack(1024); 20 | } 21 | 22 | ScavengeOopClosure::~ScavengeOopClosure() { 23 | _from = NULL; 24 | _to = NULL; 25 | 26 | delete _oop_stack; 27 | _oop_stack = NULL; 28 | } 29 | 30 | void ScavengeOopClosure::do_oop(HiObject **oop) { 31 | if (oop == NULL || *oop == NULL) { 32 | return; 33 | } 34 | 35 | // this oop has been handled, since it may be refered by Klass 36 | if (!_from->has_obj((char *) *oop)) { 37 | return; 38 | } 39 | 40 | (*oop) = copy_and_push(*oop); 41 | } 42 | 43 | void ScavengeOopClosure::do_array_list(ArrayList **alist) { 44 | if (alist == NULL || *alist == NULL) { 45 | return; 46 | } 47 | 48 | // no chance to visit list more than once. 49 | // ArrayList基本只作为HiObject内部属性使用,不会由多个对象同时引用 50 | assert(_from->has_obj((char *) *alist)); 51 | 52 | size_t size = sizeof(ArrayList); 53 | char *target = (char *) _to->allocate(size); 54 | memcpy(target, (*alist), size); 55 | (*(char **) alist) = target; 56 | 57 | (*alist)->oops_do(this); 58 | } 59 | 60 | void ScavengeOopClosure::do_array_list(ArrayList **alist) { 61 | if (alist == NULL || *alist == NULL) { 62 | return; 63 | } 64 | 65 | assert(_from->has_obj((char *) *alist)); 66 | 67 | size_t size = sizeof(ArrayList); 68 | char *target = (char *) _to->allocate(size); 69 | memcpy(target, (*alist), size); 70 | (*(char **) alist) = target; 71 | (*alist)->oops_do(this); 72 | } 73 | 74 | void ScavengeOopClosure::do_map(Map **amap) { 75 | if (amap == NULL || *amap == NULL) { 76 | return; 77 | } 78 | 79 | assert(_from->has_obj((char *) *amap)); 80 | 81 | size_t size = sizeof(Map); 82 | char *target = (char *) _to->allocate(size); 83 | memcpy(target, (*amap), size); 84 | (*(char **) amap) = target; 85 | (*amap)->oops_do(this); 86 | } 87 | 88 | void ScavengeOopClosure::do_raw_mem(char **mem, int length) { 89 | if (*mem == NULL) { 90 | return; 91 | } 92 | 93 | char *target = (char *) _to->allocate(length); 94 | memcpy(target, (*mem), length); 95 | (*mem) = target; 96 | } 97 | 98 | void ScavengeOopClosure::do_klass(Klass **k) { 99 | if (k == NULL || *k == NULL) { 100 | return; 101 | } 102 | 103 | (*k)->oops_do(this); 104 | } 105 | 106 | HiObject *ScavengeOopClosure::copy_and_push(HiObject *obj) { 107 | char *target = obj->new_address(); 108 | if (target) { 109 | // 如果已经move到了to空间, 那直接返回forwarding指针 110 | return (HiObject *) target; 111 | } 112 | 113 | // copy 114 | size_t size = obj->size(); 115 | target = (char *) _to->allocate(size); 116 | memcpy(target, obj, size); 117 | obj->set_new_address(target); 118 | 119 | // push 120 | _oop_stack->push((HiObject *) target); 121 | 122 | return (HiObject *) target; 123 | } 124 | 125 | void ScavengeOopClosure::scavenge() { 126 | // step1, mark roots 127 | process_roots(); 128 | 129 | // step2, process all objects 130 | while (!_oop_stack->empty()) { 131 | _oop_stack->pop()->oops_do(this); 132 | } 133 | } 134 | 135 | void ScavengeOopClosure::process_roots() { 136 | Universe::oops_do(this); 137 | Interpreter::get_instance()->oops_do(this); 138 | StringTable::get_instance()->oops_do(this); 139 | } 140 | -------------------------------------------------------------------------------- /memory/oopClosure.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/9/18. 3 | // 4 | 5 | #ifndef PYTHONVM_OOPCLOSURE_HPP 6 | #define PYTHONVM_OOPCLOSURE_HPP 7 | 8 | class Space; 9 | 10 | class Heap; 11 | 12 | class HiObject; 13 | 14 | class Klass; 15 | 16 | template 17 | class ArrayList; 18 | 19 | template 20 | class Map; 21 | 22 | template 23 | class Stack; 24 | 25 | class OopClosure { 26 | public: 27 | virtual void do_oop(HiObject **obj) = 0; 28 | 29 | virtual void do_array_list(ArrayList **alist) = 0; 30 | 31 | virtual void do_array_list(ArrayList **alist) = 0; 32 | 33 | virtual void do_map(Map **amap) = 0; 34 | 35 | virtual void do_raw_mem(char **mem, int length) = 0; 36 | 37 | virtual void do_klass(Klass **k) = 0; 38 | }; 39 | 40 | class ScavengeOopClosure : public OopClosure { 41 | private: 42 | Space *_from; 43 | Space *_to; 44 | Space *_meta; 45 | 46 | Stack *_oop_stack; 47 | 48 | HiObject *copy_and_push(HiObject *obj); 49 | 50 | public: 51 | ScavengeOopClosure(Space *from, Space *to, Space *meta); 52 | 53 | ~ScavengeOopClosure(); 54 | 55 | virtual void do_oop(HiObject **oop); 56 | 57 | virtual void do_array_list(ArrayList **alist); 58 | 59 | virtual void do_array_list(ArrayList **alist); 60 | 61 | virtual void do_map(Map **amap); 62 | 63 | virtual void do_raw_mem(char **mem, int length); 64 | 65 | // CAUTION : we do not move Klass, because they locate at MetaSpace. 66 | virtual void do_klass(Klass **k); 67 | 68 | void scavenge(); 69 | 70 | void process_roots(); 71 | }; 72 | 73 | #endif //PYTHONVM_OOPCLOSURE_HPP 74 | -------------------------------------------------------------------------------- /object/hiDict.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/23. 3 | // 4 | 5 | #include "object/hiDict.hpp" 6 | #include "object/hiList.hpp" 7 | #include "object/hiInteger.hpp" 8 | #include "object/hiString.hpp" 9 | #include "runtime/functionObject.hpp" 10 | #include "runtime/universe.hpp" 11 | #include "runtime/stringTable.hpp" 12 | #include "memory/oopClosure.hpp" 13 | #include 14 | 15 | DictKlass *DictKlass::instance = NULL; 16 | 17 | DictKlass::DictKlass() { 18 | } 19 | 20 | DictKlass *DictKlass::get_instance() { 21 | if (instance == NULL) { 22 | instance = new DictKlass(); 23 | } 24 | 25 | return instance; 26 | } 27 | 28 | void DictKlass::initialize() { 29 | HiDict *klass_dict = new HiDict(); 30 | klass_dict->put(new HiString("setdefault"), new FunctionObject(dict_set_default)); 31 | klass_dict->put(new HiString("remove"), 32 | new FunctionObject(dict_remove)); 33 | klass_dict->put(new HiString("pop"), 34 | new FunctionObject(dict_pop)); 35 | klass_dict->put(new HiString("keys"), 36 | new FunctionObject(dict_keys)); 37 | klass_dict->put(new HiString("values"), 38 | new FunctionObject(dict_values)); 39 | klass_dict->put(new HiString("items"), 40 | new FunctionObject(dict_items)); 41 | klass_dict->put(new HiString("iterkeys"), 42 | new FunctionObject(dict_iterkeys)); 43 | klass_dict->put(new HiString("itervalues"), 44 | new FunctionObject(dict_itervalues)); 45 | klass_dict->put(new HiString("iteritems"), 46 | new FunctionObject(dict_iteritems)); 47 | set_klass_dict(klass_dict); 48 | set_name(new HiString("dict")); 49 | (new HiTypeObject())->set_own_klass(this); 50 | add_super(ObjectKlass::get_instance()); 51 | } 52 | 53 | /* 54 | * Iterations for dict object 55 | */ 56 | template 57 | DictIteratorKlass *DictIteratorKlass::instance = NULL; 58 | 59 | template 60 | DictIteratorKlass *DictIteratorKlass::get_instance() { 61 | if (instance == NULL) { 62 | instance = new DictIteratorKlass(); 63 | } 64 | 65 | return instance; 66 | } 67 | 68 | template 69 | DictIteratorKlass::DictIteratorKlass() { 70 | const char *klass_names[] = { 71 | "dictionary-keyiterator", 72 | "dictionary-valueiterator", 73 | "dictionary-itemiterator", 74 | }; 75 | HiDict *klass_dict = new HiDict(); 76 | klass_dict->put(new HiString("next"), 77 | new FunctionObject(dictiterator_next)); 78 | set_klass_dict(klass_dict); 79 | set_name(new HiString(klass_names[iter_type])); 80 | } 81 | 82 | DictIterator::DictIterator(HiDict *dict) { 83 | _owner = dict; 84 | _iter_cnt = 0; 85 | } 86 | 87 | HiObject *DictKlass::subscr(HiObject *x, HiObject *y) { 88 | assert(x && x->klass() == (Klass *) this); 89 | return ((HiDict *) x)->map()->get(y); 90 | } 91 | 92 | HiObject *DictKlass::iter(HiObject *x) { 93 | HiObject *it = new DictIterator((HiDict *) x); 94 | it->set_klass(DictIteratorKlass::get_instance()); 95 | return it; 96 | } 97 | 98 | void DictKlass::print(HiObject *obj) { 99 | HiDict *dict_obj = (HiDict *) obj; 100 | assert(dict_obj && dict_obj->klass() == (Klass *) this); 101 | 102 | printf("{"); 103 | int size = dict_obj->_map->size(); 104 | if (size >= 1) { 105 | dict_obj->_map->entries()[0]._k->print(); 106 | printf(":"); 107 | dict_obj->_map->entries()[0]._v->print(); 108 | } 109 | 110 | for (int i = 1; i < size; i++) { 111 | printf(", "); 112 | dict_obj->_map->entries()[i]._k->print(); 113 | printf(":"); 114 | dict_obj->_map->entries()[i]._v->print(); 115 | } 116 | 117 | printf("}"); 118 | } 119 | 120 | void DictKlass::store_subscr(HiObject *x, HiObject *y, HiObject *z) { 121 | assert(x && x->klass() == (Klass *) this); 122 | ((HiDict *) x)->put(y, z); 123 | } 124 | 125 | void DictKlass::del_subscr(HiObject *x, HiObject *y) { 126 | assert(x && x->klass() == (Klass *) this); 127 | ((HiDict *) x)->remove(y); 128 | } 129 | 130 | HiObject *DictKlass::allocate_instance(HiObject *callable, ArrayList *args) { 131 | if (!args || args->length() == 0) { 132 | return new HiDict(); 133 | } else { 134 | return NULL; 135 | } 136 | } 137 | 138 | size_t DictKlass::size() { 139 | return sizeof(HiDict); 140 | } 141 | 142 | void DictKlass::oops_do(OopClosure *f, HiObject *obj) { 143 | assert(obj->klass() == (Klass *) this); 144 | 145 | f->do_map(&((HiDict *) obj)->_map); 146 | } 147 | 148 | HiDict::HiDict() { 149 | _map = new Map(); 150 | set_klass(DictKlass::get_instance()); 151 | } 152 | 153 | HiDict::HiDict(Map *x) { 154 | _map = x; 155 | set_klass(DictKlass::get_instance()); 156 | } 157 | 158 | void HiDict::update(HiDict *dict) { 159 | for (int i = 0; i < dict->size(); i++) { 160 | put(dict->map()->get_key(i), dict->map()->get_value(i)); 161 | } 162 | } 163 | 164 | HiObject *dict_set_default(ObjList args) { 165 | HiDict *dict = (HiDict *) (args->get(0)); 166 | HiObject *key = args->get(1); 167 | HiObject *value = args->get(2); 168 | 169 | if (!dict->has_key(key)) { 170 | dict->put(key, value); 171 | } 172 | 173 | return Universe::HiNone; 174 | } 175 | 176 | HiObject *dict_remove(ObjList args) { 177 | HiObject *x = args->get(0); 178 | HiObject *y = args->get(1); 179 | 180 | return ((HiDict *) x)->remove(y); 181 | } 182 | 183 | HiObject *dict_pop(ObjList args) { 184 | HiObject *x = args->get(0); 185 | HiObject *y = args->get(1); 186 | 187 | ((HiDict *) x)->remove(y); 188 | 189 | return Universe::HiNone; 190 | } 191 | 192 | HiObject *dict_keys(ObjList args) { 193 | HiDict *x = (HiDict *) (args->get(0)); 194 | HiList *keys = new HiList(); 195 | 196 | for (int i = 0; i < x->size(); i++) { 197 | keys->append(x->map()->get_key(i)); 198 | } 199 | 200 | return keys; 201 | } 202 | 203 | HiObject *dict_values(ObjList args) { 204 | HiDict *x = (HiDict *) (args->get(0)); 205 | HiList *values = new HiList(); 206 | 207 | for (int i = 0; i < x->size(); i++) { 208 | values->append(x->map()->get_value(i)); 209 | } 210 | 211 | return values; 212 | } 213 | 214 | HiObject *dict_items(ObjList args) { 215 | HiDict *x = (HiDict *) (args->get(0)); 216 | HiList *items = new HiList(); 217 | 218 | for (int i = 0; i < x->size(); i++) { 219 | HiList *item = new HiList(); 220 | item->append(x->map()->get_key(i)); 221 | item->append(x->map()->get_value(i)); 222 | items->append(item); 223 | } 224 | 225 | return items; 226 | } 227 | 228 | HiObject *dict_iterkeys(ObjList args) { 229 | HiDict *x = (HiDict *) (args->get(0)); 230 | HiObject *it = new DictIterator(x); 231 | it->set_klass(DictIteratorKlass::get_instance()); 232 | return it; 233 | } 234 | 235 | HiObject *dict_itervalues(ObjList args) { 236 | HiDict *x = (HiDict *) (args->get(0)); 237 | HiObject *it = new DictIterator(x); 238 | it->set_klass(DictIteratorKlass::get_instance()); 239 | return it; 240 | } 241 | 242 | HiObject *dict_iteritems(ObjList args) { 243 | HiDict *x = (HiDict *) (args->get(0)); 244 | HiObject *it = new DictIterator(x); 245 | it->set_klass(DictIteratorKlass::get_instance()); 246 | return it; 247 | } 248 | 249 | template 250 | HiObject *DictIteratorKlass::next(HiObject *x) { 251 | DictIterator *iter = (DictIterator *) x; 252 | 253 | HiDict *adict = iter->owner(); 254 | int iter_cnt = iter->iter_cnt(); 255 | if (iter_cnt < adict->map()->size()) { 256 | HiObject *obj; 257 | if (iter_type == ITER_KEY) 258 | obj = adict->map()->get_key(iter_cnt); 259 | else if (iter_type == ITER_VALUE) { 260 | obj = adict->map()->get_value(iter_cnt); 261 | } else if (iter_type == ITER_ITEM) { 262 | HiList *lobj = new HiList(); 263 | lobj->append(adict->map()->get_key(iter_cnt)); 264 | lobj->append(adict->map()->get_value(iter_cnt)); 265 | obj = lobj; 266 | } 267 | iter->inc_cnt(); 268 | return obj; 269 | } else { 270 | // TODO : we need Traceback here to mark iteration end 271 | return NULL; 272 | } 273 | } 274 | 275 | // TODO remove 276 | HiObject *dictiterator_next(ObjList args) { 277 | DictIterator *iter = (DictIterator *) (args->get(0)); 278 | return iter->klass()->next(iter); 279 | } 280 | -------------------------------------------------------------------------------- /object/hiDict.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/23. 3 | // 4 | 5 | #ifndef PYTHONVM_HIDICT_HPP 6 | #define PYTHONVM_HIDICT_HPP 7 | 8 | #include "object/hiObject.hpp" 9 | #include "util/map.hpp" 10 | 11 | class DictKlass : public Klass { 12 | private: 13 | DictKlass(); 14 | static DictKlass* instance; 15 | 16 | public: 17 | static DictKlass* get_instance(); 18 | void initialize(); 19 | 20 | virtual HiObject* subscr (HiObject* x, HiObject* y); 21 | virtual HiObject* iter(HiObject* x); 22 | virtual void print(HiObject* obj); 23 | virtual void store_subscr(HiObject* x, HiObject* y, HiObject* z); 24 | virtual void del_subscr (HiObject* x, HiObject* y); 25 | 26 | virtual HiObject *allocate_instance(HiObject* callable, ArrayList *args); 27 | 28 | virtual size_t size(); 29 | virtual void oops_do(OopClosure *f, HiObject *obj); 30 | }; 31 | 32 | class HiDict : public HiObject { 33 | friend class DictKlass; 34 | private: 35 | Map* _map; 36 | 37 | public: 38 | HiDict(); 39 | HiDict(Map* map); 40 | 41 | Map* map() { return _map; } 42 | void put(HiObject* k, HiObject* v) { _map->put(k, v); } 43 | HiObject* get(HiObject* k) { return _map->get(k); } 44 | bool has_key(HiObject* k) { return _map->has_key(k); } 45 | int size() { return _map->size(); } 46 | HiObject* remove(HiObject* k) { return _map->remove(k); } 47 | 48 | void update(HiDict *x); 49 | }; 50 | 51 | HiObject* dict_set_default(ObjList args); 52 | HiObject* dict_remove(ObjList args); 53 | HiObject* dict_pop(ObjList args); 54 | HiObject* dict_keys(ObjList args); 55 | HiObject* dict_values(ObjList args); 56 | HiObject* dict_items(ObjList args); 57 | HiObject* dict_iterkeys(ObjList args); 58 | HiObject* dict_itervalues(ObjList args); 59 | HiObject* dict_iteritems(ObjList args); 60 | 61 | enum ITER_TYPE { 62 | ITER_KEY = 0, 63 | ITER_VALUE, 64 | ITER_ITEM 65 | }; 66 | 67 | template 68 | class DictIteratorKlass : public Klass { 69 | private: 70 | static DictIteratorKlass *instance; 71 | DictIteratorKlass(); 72 | 73 | public: 74 | static DictIteratorKlass *get_instance(); 75 | virtual HiObject *iter(HiObject *x) { return x; } 76 | virtual HiObject *next(HiObject *x); 77 | }; 78 | 79 | class DictIterator : public HiObject { 80 | private: 81 | HiDict *_owner; 82 | int _iter_cnt; 83 | public: 84 | DictIterator(HiDict *owner); 85 | 86 | HiDict *owner() { return _owner; } 87 | int iter_cnt() { return _iter_cnt; } 88 | void inc_cnt() { _iter_cnt++; } 89 | }; 90 | 91 | // TODO remove 92 | HiObject* dictiterator_next(ObjList args); 93 | 94 | #endif //PYTHONVM_HIDICT_HPP 95 | -------------------------------------------------------------------------------- /object/hiInteger.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 0000/8/14. 3 | // 4 | 5 | #include 6 | 7 | #include "object/klass.hpp" 8 | #include "object/hiDict.hpp" 9 | #include "object/hiString.hpp" 10 | #include "object/hiInteger.hpp" 11 | #include "runtime/universe.hpp" 12 | 13 | IntegerKlass *IntegerKlass::instance = NULL; 14 | 15 | IntegerKlass::IntegerKlass() { 16 | } 17 | 18 | void IntegerKlass::initialize() { 19 | set_klass_dict(new HiDict()); 20 | set_name(new HiString("int")); 21 | (new HiTypeObject())->set_own_klass(this); 22 | add_super(ObjectKlass::get_instance()); 23 | } 24 | 25 | IntegerKlass *IntegerKlass::get_instance() { 26 | if (instance == NULL) { 27 | instance = new IntegerKlass(); 28 | } 29 | 30 | return instance; 31 | } 32 | 33 | HiInteger::HiInteger(int x) { 34 | _value = x; 35 | set_klass(IntegerKlass::get_instance()); 36 | } 37 | 38 | void IntegerKlass::print(HiObject *obj) { 39 | HiInteger *int_obj = (HiInteger *) obj; 40 | 41 | assert(int_obj && (int_obj->klass()) == ((Klass *) this)); 42 | 43 | printf("%d", int_obj->value()); 44 | } 45 | 46 | HiObject *IntegerKlass::greater(HiObject *x, HiObject *y) { 47 | HiInteger *ix = (HiInteger *) x; 48 | HiInteger *iy = (HiInteger *) y; 49 | 50 | assert(ix && (ix->klass() == (Klass *) this)); 51 | assert(iy && (iy->klass() == (Klass *) this)); 52 | 53 | if (ix->value() > iy->value()) 54 | return Universe::HiTrue; 55 | else 56 | return Universe::HiFalse; 57 | } 58 | 59 | HiObject *IntegerKlass::less(HiObject *x, HiObject *y) { 60 | HiInteger *ix = (HiInteger *) x; 61 | assert(ix && (ix->klass() == (Klass *) this)); 62 | 63 | if (x->klass() != y->klass()) { 64 | if (Klass::compare_klass(x->klass(), y->klass()) < 0) { 65 | return Universe::HiTrue; 66 | } else { 67 | return Universe::HiFalse; 68 | } 69 | } 70 | 71 | HiInteger *iy = (HiInteger *) y; 72 | assert(iy && (iy->klass() == (Klass *) this)); 73 | 74 | if (ix->value() < iy->value()) { 75 | return Universe::HiTrue; 76 | } else { 77 | return Universe::HiFalse; 78 | } 79 | } 80 | 81 | HiObject *IntegerKlass::equal(HiObject *x, HiObject *y) { 82 | if (x->klass() != y->klass()) 83 | return Universe::HiFalse; 84 | 85 | HiInteger *ix = (HiInteger *) x; 86 | HiInteger *iy = (HiInteger *) y; 87 | 88 | assert(ix && (ix->klass() == (Klass *) this)); 89 | assert(iy && (iy->klass() == (Klass *) this)); 90 | 91 | if (ix->value() == iy->value()) 92 | return Universe::HiTrue; 93 | else 94 | return Universe::HiFalse; 95 | } 96 | 97 | HiObject *IntegerKlass::not_equal(HiObject *x, HiObject *y) { 98 | HiInteger *ix = (HiInteger *) x; 99 | HiInteger *iy = (HiInteger *) y; 100 | 101 | assert(ix && (ix->klass() == (Klass *) this)); 102 | assert(iy && (iy->klass() == (Klass *) this)); 103 | 104 | if (ix->value() != iy->value()) 105 | return Universe::HiTrue; 106 | else 107 | return Universe::HiFalse; 108 | } 109 | 110 | HiObject *IntegerKlass::ge(HiObject *x, HiObject *y) { 111 | HiInteger *ix = (HiInteger *) x; 112 | HiInteger *iy = (HiInteger *) y; 113 | 114 | assert(ix && (ix->klass() == (Klass *) this)); 115 | assert(iy && (iy->klass() == (Klass *) this)); 116 | 117 | if (ix->value() >= iy->value()) 118 | return Universe::HiTrue; 119 | else 120 | return Universe::HiFalse; 121 | } 122 | 123 | HiObject *IntegerKlass::le(HiObject *x, HiObject *y) { 124 | HiInteger *ix = (HiInteger *) x; 125 | HiInteger *iy = (HiInteger *) y; 126 | 127 | assert(ix && (ix->klass() == (Klass *) this)); 128 | assert(iy && (iy->klass() == (Klass *) this)); 129 | 130 | if (ix->value() <= iy->value()) 131 | return Universe::HiTrue; 132 | else 133 | return Universe::HiFalse; 134 | } 135 | 136 | HiObject *IntegerKlass::add(HiObject *x, HiObject *y) { 137 | HiInteger *ix = (HiInteger *) x; 138 | HiInteger *iy = (HiInteger *) y; 139 | 140 | assert(ix && (ix->klass() == (Klass *) this)); 141 | assert(iy && (iy->klass() == (Klass *) this)); 142 | 143 | return new HiInteger(ix->value() + iy->value()); 144 | } 145 | 146 | HiObject *IntegerKlass::sub(HiObject *x, HiObject *y) { 147 | HiInteger *ix = (HiInteger *) x; 148 | HiInteger *iy = (HiInteger *) y; 149 | 150 | assert(ix && (ix->klass() == (Klass *) this)); 151 | assert(iy && (iy->klass() == (Klass *) this)); 152 | 153 | return new HiInteger(ix->value() - iy->value()); 154 | } 155 | 156 | HiObject *IntegerKlass::mul(HiObject *x, HiObject *y) { 157 | HiInteger *ix = (HiInteger *) x; 158 | HiInteger *iy = (HiInteger *) y; 159 | 160 | assert(ix && (ix->klass() == (Klass *) this)); 161 | assert(iy && (iy->klass() == (Klass *) this)); 162 | 163 | return new HiInteger(ix->value() * iy->value()); 164 | } 165 | 166 | HiObject *IntegerKlass::div(HiObject *x, HiObject *y) { 167 | HiInteger *ix = (HiInteger *) x; 168 | HiInteger *iy = (HiInteger *) y; 169 | 170 | assert(ix && (ix->klass() == (Klass *) this)); 171 | assert(iy && (iy->klass() == (Klass *) this)); 172 | assert(iy->value() != 0); 173 | 174 | return new HiInteger(ix->value() / iy->value()); 175 | } 176 | 177 | HiObject *IntegerKlass::mod(HiObject *x, HiObject *y) { 178 | HiInteger *ix = (HiInteger *) x; 179 | HiInteger *iy = (HiInteger *) y; 180 | 181 | assert(ix && (ix->klass() == (Klass *) this)); 182 | assert(iy && (iy->klass() == (Klass *) this)); 183 | assert(iy->value() != 0); 184 | 185 | return new HiInteger(ix->value() % iy->value()); 186 | } 187 | 188 | HiObject *IntegerKlass::allocate_instance(HiObject *callable, ArrayList *args) { 189 | if (!args || args->length() == 0) { 190 | return new HiInteger(0); 191 | } else { 192 | return NULL; 193 | } 194 | } 195 | 196 | size_t IntegerKlass::size() { 197 | return sizeof(HiInteger); 198 | } 199 | 200 | void IntegerKlass::oops_do(OopClosure *f, HiObject *obj) { 201 | // do nothing 202 | // only overwrite warning message in Klass 203 | } 204 | -------------------------------------------------------------------------------- /object/hiInteger.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/14. 3 | // 4 | 5 | #ifndef PYTHONVM_HIINTEGER_HPP 6 | #define PYTHONVM_HIINTEGER_HPP 7 | 8 | #include "hiObject.hpp" 9 | 10 | class IntegerKlass : public Klass { 11 | private: 12 | IntegerKlass(); 13 | static IntegerKlass *instance; 14 | 15 | public: 16 | static IntegerKlass *get_instance(); 17 | void initialize(); 18 | 19 | virtual void print(HiObject* obj); 20 | 21 | virtual HiObject* greater (HiObject* x, HiObject* y); 22 | virtual HiObject* less (HiObject* x, HiObject* y); 23 | virtual HiObject* equal (HiObject* x, HiObject* y); 24 | virtual HiObject* not_equal(HiObject* x, HiObject* y); 25 | virtual HiObject* ge (HiObject* x, HiObject* y); 26 | virtual HiObject* le (HiObject* x, HiObject* y); 27 | 28 | virtual HiObject* add(HiObject* x, HiObject* y); 29 | virtual HiObject* sub(HiObject* x, HiObject* y); 30 | virtual HiObject* mul(HiObject* x, HiObject* y); 31 | virtual HiObject* div(HiObject* x, HiObject* y); 32 | virtual HiObject* mod(HiObject* x, HiObject* y); 33 | 34 | virtual HiObject *allocate_instance(HiObject* callable, ArrayList *args); 35 | 36 | virtual size_t size(); 37 | virtual void oops_do(OopClosure *f, HiObject *obj); 38 | }; 39 | 40 | class HiInteger : public HiObject { 41 | private: 42 | int _value; 43 | 44 | public: 45 | HiInteger(int x); 46 | 47 | int value() { 48 | return _value; 49 | }; 50 | }; 51 | 52 | #endif //PYTHONVM_HIINTEGER_HPP 53 | -------------------------------------------------------------------------------- /object/hiList.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/20. 3 | // 4 | 5 | #include "object/hiList.hpp" 6 | #include "object/hiInteger.hpp" 7 | #include "object/hiString.hpp" 8 | #include "object/hiDict.hpp" 9 | #include "runtime/interpreter.hpp" 10 | #include "runtime/universe.hpp" 11 | #include "runtime/functionObject.hpp" 12 | #include "memory/oopClosure.hpp" 13 | 14 | ListKlass *ListKlass::instance = NULL; 15 | 16 | ListKlass::ListKlass() { 17 | } 18 | 19 | void ListKlass::initialize() { 20 | HiDict *klass_dict = new HiDict(); 21 | klass_dict->put(new HiString("append"), new FunctionObject(list_append)); 22 | klass_dict->put(new HiString("insert"), new FunctionObject(list_insert)); 23 | klass_dict->put(new HiString("index"), new FunctionObject(list_index)); 24 | klass_dict->put(new HiString("pop"), new FunctionObject(list_pop)); 25 | klass_dict->put(new HiString("popleft"), new FunctionObject(list_popleft)); 26 | klass_dict->put(new HiString("remove"), new FunctionObject(list_remove)); 27 | klass_dict->put(new HiString("reverse"), new FunctionObject(list_reverse)); 28 | klass_dict->put(new HiString("sort"), new FunctionObject(list_sort)); 29 | set_klass_dict(klass_dict); 30 | 31 | (new HiTypeObject())->set_own_klass(this); 32 | set_name(new HiString("list")); 33 | add_super(ObjectKlass::get_instance()); 34 | } 35 | 36 | ListKlass *ListKlass::get_instance() { 37 | if (instance == NULL) 38 | instance = new ListKlass(); 39 | 40 | return instance; 41 | } 42 | 43 | HiObject *ListKlass::add(HiObject *x, HiObject *y) { 44 | HiList *lx = (HiList *) x; 45 | assert(lx && lx->klass() == (Klass *) this); 46 | HiList *ly = (HiList *) y; 47 | assert(ly && ly->klass() == (Klass *) this); 48 | 49 | HiList *z = new HiList(); 50 | for (int i = 0; i < lx->size(); i++) { 51 | z->inner_list()->set(i, lx->inner_list()->get(i)); 52 | } 53 | 54 | for (int i = 0; i < ly->size(); i++) { 55 | z->inner_list()->set(i + lx->size(), 56 | ly->inner_list()->get(i)); 57 | } 58 | 59 | return z; 60 | } 61 | 62 | HiObject *ListKlass::mul(HiObject *x, HiObject *y) { 63 | HiList *lx = (HiList *) x; 64 | assert(lx && lx->klass() == (Klass *) this); 65 | HiInteger *iy = (HiInteger *) y; 66 | assert(iy && iy->klass() == IntegerKlass::get_instance()); 67 | 68 | HiList *z = new HiList(); 69 | for (int i = 0; i < iy->value(); i++) { 70 | for (int j = 0; j < lx->size(); j++) { 71 | z->inner_list()->set(i * lx->size() + j, 72 | lx->inner_list()->get(j)); 73 | } 74 | } 75 | 76 | return z; 77 | } 78 | 79 | void ListKlass::print(HiObject *x) { 80 | HiList *lx = (HiList *) x; 81 | assert(lx && lx->klass() == (Klass *) this); 82 | 83 | printf("["); 84 | 85 | int size = lx->_inner_list->size(); 86 | if (size >= 1) 87 | lx->_inner_list->get(0)->print(); 88 | 89 | for (int i = 1; i < size; i++) { 90 | printf(", "); 91 | lx->_inner_list->get(i)->print(); 92 | } 93 | printf("]"); 94 | } 95 | 96 | HiObject *ListKlass::subscr(HiObject *x, HiObject *y) { 97 | assert(x && x->klass() == (Klass *) this); 98 | assert(y && y->klass() == (Klass *) IntegerKlass::get_instance()); 99 | 100 | HiList *lx = (HiList *) x; 101 | HiInteger *iy = (HiInteger *) y; 102 | 103 | return lx->inner_list()->get(iy->value()); 104 | } 105 | 106 | void ListKlass::store_subscr(HiObject *x, HiObject *y, HiObject *z) { 107 | assert(x && x->klass() == (Klass *) this); 108 | assert(y && y->klass() == IntegerKlass::get_instance()); 109 | 110 | HiList *lx = (HiList *) x; 111 | HiInteger *iy = (HiInteger *) y; 112 | 113 | lx->inner_list()->set(iy->value(), z); 114 | } 115 | 116 | void ListKlass::del_subscr(HiObject *x, HiObject *y) { 117 | assert(x && x->klass() == (Klass *) this); 118 | assert(y && y->klass() == IntegerKlass::get_instance()); 119 | 120 | HiList *lx = (HiList *) x; 121 | HiInteger *iy = (HiInteger *) y; 122 | 123 | lx->inner_list()->delete_index(iy->value()); 124 | } 125 | 126 | HiObject *ListKlass::contains(HiObject *x, HiObject *y) { 127 | HiList *lx = (HiList *) x; 128 | assert(lx && lx->klass() == (Klass *) this); 129 | 130 | int size = lx->inner_list()->size(); 131 | for (int i = 0; i < size; ++i) { 132 | if (lx->inner_list()->get(i)->equal(y) == Universe::HiTrue) { 133 | return Universe::HiTrue; 134 | } 135 | } 136 | 137 | return Universe::HiFalse; 138 | } 139 | 140 | HiObject *ListKlass::less(HiObject *x, HiObject *y) { 141 | HiList *lx = (HiList *) x; 142 | assert(lx && lx->klass() == (Klass *) this); 143 | 144 | if (x->klass() != y->klass()) { 145 | if (Klass::compare_klass(x->klass(), y->klass()) < 0) { 146 | return Universe::HiTrue; 147 | } else { 148 | return Universe::HiFalse; 149 | } 150 | } 151 | 152 | HiList *ly = (HiList *) y; 153 | assert(ly && ly->klass() == (Klass *) this); 154 | 155 | int len = lx->size() < ly->size() ? 156 | lx->size() : ly->size(); 157 | 158 | for (int i = 0; i < len; i++) { 159 | if (lx->get(i)->less(ly->get(i)) == Universe::HiTrue) { 160 | { 161 | return Universe::HiTrue; 162 | } 163 | } else if (lx->get(i)->equal(ly->get(i)) != Universe::HiTrue) { 164 | { 165 | return Universe::HiFalse; 166 | } 167 | } 168 | } 169 | 170 | if (lx->size() < ly->size()) { 171 | return Universe::HiTrue; 172 | } 173 | 174 | return Universe::HiFalse; 175 | } 176 | 177 | HiObject *ListKlass::len(HiObject *x) { 178 | assert(x->klass() == this); 179 | return new HiInteger(((HiList *) x)->size()); 180 | } 181 | 182 | HiObject *ListKlass::iter(HiObject *x) { 183 | assert(x && x->klass() == this); 184 | return new ListIterator((HiList *) x); 185 | } 186 | 187 | HiObject *ListKlass::allocate_instance(HiObject *callable, ArrayList *args) { 188 | if (!args || args->length() == 0) { 189 | return new HiList(); 190 | } else { 191 | return NULL; 192 | } 193 | } 194 | 195 | HiList::HiList() { 196 | set_klass(ListKlass::get_instance()); 197 | _inner_list = new ArrayList(); 198 | } 199 | 200 | HiList::HiList(ObjList ol) { 201 | set_klass(ListKlass::get_instance()); 202 | _inner_list = ol; 203 | } 204 | 205 | int HiList::index(HiObject *t) { 206 | for (int i = 0; i < size(); i++) { 207 | if (get(i) == t) { 208 | return i; 209 | } 210 | } 211 | 212 | return -1; 213 | } 214 | 215 | HiObject *list_append(ObjList args) { 216 | HiList *list = (HiList *) (args->get(0)); 217 | HiObject *var = args->get(1); 218 | list->append(var); 219 | return Universe::HiNone; 220 | } 221 | 222 | HiObject *list_insert(ObjList args) { 223 | HiList *list = (HiList *) (args->get(0)); 224 | HiObject *index = args->get(1); 225 | HiObject *var = args->get(2); 226 | 227 | HiInteger *i = (HiInteger *) index; 228 | assert(i && i->klass() == IntegerKlass::get_instance()); 229 | 230 | list->insert(i->value(), var); 231 | return Universe::HiNone; 232 | } 233 | 234 | HiObject *list_index(ObjList args) { 235 | HiList *list = (HiList *) (args->get(0)); 236 | HiObject *target = (HiObject *) (args->get(1)); 237 | 238 | assert(list && list->klass() == ListKlass::get_instance()); 239 | 240 | for (int i = 0; i < list->size(); ++i) { 241 | if (list->get(i)->equal(target) == Universe::HiTrue) { 242 | return new HiInteger(i); 243 | } 244 | } 245 | 246 | return NULL; 247 | } 248 | 249 | HiObject *list_pop(ObjList args) { 250 | HiList *list = (HiList *) (args->get(0)); 251 | assert(list && list->klass() == ListKlass::get_instance()); 252 | return list->pop(); 253 | } 254 | 255 | HiObject *list_popleft(ObjList args) { 256 | HiList *list = (HiList *) (args->get(0)); 257 | assert(list && list->klass() == ListKlass::get_instance()); 258 | HiObject *left = list->get(0); 259 | list->delete_index(0); 260 | return left; 261 | } 262 | 263 | HiObject *list_remove(ObjList args) { 264 | HiList *list = (HiList *) (args->get(0)); 265 | HiObject *target = args->get(1); 266 | 267 | assert(list && list->klass() == ListKlass::get_instance()); 268 | 269 | for (int i = 0; i < list->size(); ++i) { 270 | if (list->get(i)->equal(target) == Universe::HiTrue) { 271 | list->inner_list()->delete_index(i); 272 | } 273 | } 274 | 275 | return Universe::HiNone; 276 | } 277 | 278 | HiObject *list_reverse(ObjList args) { 279 | HiList *list = (HiList *) (args->get(0)); 280 | assert(list && list->klass() == ListKlass::get_instance()); 281 | 282 | int i = 0; 283 | int j = list->size() - 1; 284 | while (i < j) { 285 | HiObject *tmp = list->get(i); 286 | list->set(i, list->get(j)); 287 | list->set(j, tmp); 288 | 289 | i++; 290 | j--; 291 | } 292 | 293 | return Universe::HiNone; 294 | } 295 | 296 | HiObject *list_sort(ObjList args) { 297 | HiList *list = (HiList *) (args->get(0)); 298 | assert(list && list->klass() == ListKlass::get_instance()); 299 | 300 | // bubble sort 301 | int size = list->size(); 302 | for (int i = 0; i < size; i++) { 303 | for (int j = size - 1; j > i; j--) { 304 | if (list->get(j)->less(list->get(j - 1)) == Universe::HiTrue) { 305 | HiObject *tmp = list->get(j); 306 | list->set(j, list->get(j - 1)); 307 | list->set(j - 1, tmp); 308 | } 309 | } 310 | } 311 | 312 | return Universe::HiNone; 313 | } 314 | 315 | ListIteratorKlass *ListIteratorKlass::instance = NULL; 316 | 317 | ListIteratorKlass *ListIteratorKlass::get_instance() { 318 | if (instance == NULL) 319 | instance = new ListIteratorKlass(); 320 | 321 | return instance; 322 | } 323 | 324 | ListIteratorKlass::ListIteratorKlass() { 325 | HiDict *klass_dict = new HiDict(); 326 | klass_dict->put(new HiString("next"), 327 | new FunctionObject(listiterator_next)); 328 | set_klass_dict(klass_dict); 329 | } 330 | 331 | ListIterator::ListIterator(HiList *list) { 332 | _owner = list; 333 | _iter_cnt = 0; 334 | set_klass(ListIteratorKlass::get_instance()); 335 | } 336 | 337 | HiObject *listiterator_next(ObjList args) { 338 | ListIterator *iter = (ListIterator *) (args->get(0)); 339 | 340 | HiList *alist = iter->owner(); 341 | int iter_cnt = iter->iter_cnt(); 342 | if (iter_cnt < alist->inner_list()->size()) { 343 | HiObject *obj = alist->get(iter_cnt); 344 | iter->inc_cnt(); 345 | return obj; 346 | } else { 347 | // TODO : we need Traceback here to mark iteration end 348 | return NULL; 349 | } 350 | } 351 | 352 | size_t ListKlass::size() { 353 | return sizeof(HiList); 354 | } 355 | 356 | void ListKlass::oops_do(OopClosure *f, HiObject *obj) { 357 | assert(obj && obj->klass() == (Klass *) this); 358 | 359 | f->do_array_list(&((HiList *) obj)->_inner_list); 360 | } 361 | -------------------------------------------------------------------------------- /object/hiList.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/20. 3 | // 4 | 5 | #ifndef PYTHONVM_HILIST_HPP 6 | #define PYTHONVM_HILIST_HPP 7 | 8 | #include "klass.hpp" 9 | #include "object/hiObject.hpp" 10 | #include "util/arrayList.hpp" 11 | 12 | class ListKlass : public Klass { 13 | private: 14 | ListKlass(); 15 | 16 | static ListKlass *instance; 17 | 18 | public: 19 | static ListKlass *get_instance(); 20 | void initialize(); 21 | 22 | virtual HiObject *add(HiObject *x, HiObject *y); 23 | virtual HiObject *mul(HiObject *x, HiObject *y); 24 | 25 | virtual void print(HiObject *obj); 26 | virtual HiObject *subscr(HiObject *x, HiObject *y); 27 | virtual void store_subscr(HiObject *x, HiObject *y, HiObject *z); 28 | virtual void del_subscr(HiObject *x, HiObject *y); 29 | virtual HiObject *contains(HiObject *x, HiObject *y); 30 | virtual HiObject *less(HiObject *x, HiObject *y); 31 | virtual HiObject *len(HiObject *x); 32 | virtual HiObject *iter(HiObject* x); 33 | 34 | virtual HiObject *allocate_instance(HiObject* callable, ArrayList *args); 35 | 36 | virtual size_t size(); 37 | virtual void oops_do(OopClosure *f, HiObject *obj); 38 | }; 39 | 40 | class HiList : public HiObject { 41 | friend class ListKlass; 42 | 43 | private: 44 | ArrayList *_inner_list; 45 | 46 | public: 47 | HiList(); 48 | HiList(ObjList ol); 49 | ArrayList* inner_list() { return _inner_list; } 50 | 51 | int size() { return _inner_list->size(); } 52 | void append(HiObject* obj) { _inner_list->add(obj); } 53 | void insert(int i, HiObject* o) { _inner_list->insert(i, o); } 54 | HiObject* pop() { return _inner_list->pop(); } 55 | HiObject* get(int index) { return _inner_list->get(index); } 56 | void set(int i, HiObject* o) { _inner_list->set(i, o); } 57 | HiObject* top() { return get(size() - 1); } 58 | 59 | int index(HiObject *obj); 60 | void delete_index(int index) { _inner_list->delete_index(index); } 61 | }; 62 | 63 | HiObject *list_append(ObjList args); 64 | HiObject *list_insert(ObjList args); 65 | HiObject *list_index(ObjList args); 66 | HiObject *list_pop(ObjList args); 67 | HiObject *list_popleft(ObjList args); 68 | HiObject *list_remove(ObjList args); 69 | HiObject *list_reverse(ObjList args); 70 | HiObject *list_sort(ObjList args); 71 | 72 | class ListIteratorKlass : public Klass { 73 | private: 74 | static ListIteratorKlass *instance; 75 | ListIteratorKlass(); 76 | 77 | public: 78 | static ListIteratorKlass *get_instance(); 79 | }; 80 | 81 | class ListIterator : public HiObject { 82 | private: 83 | HiList* _owner; 84 | int _iter_cnt; 85 | 86 | public: 87 | ListIterator(HiList *owner); 88 | 89 | HiList* owner() { return _owner; } 90 | int iter_cnt() { return _iter_cnt; } 91 | void inc_cnt() { _iter_cnt++; } 92 | }; 93 | 94 | HiObject *listiterator_next(ObjList args); 95 | 96 | #endif //PYTHONVM_HILIST_HPP 97 | -------------------------------------------------------------------------------- /object/hiObject.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/15. 3 | // 4 | 5 | #include "runtime/universe.hpp" 6 | #include "runtime/stringTable.hpp" 7 | #include "hiObject.hpp" 8 | #include "object/hiDict.hpp" 9 | #include "object/hiString.hpp" 10 | #include "runtime/universe.hpp" 11 | #include "runtime/functionObject.hpp" 12 | #include "memory/heap.hpp" 13 | #include "memory/oopClosure.hpp" 14 | 15 | ObjectKlass *ObjectKlass::instance = NULL; 16 | 17 | ObjectKlass::ObjectKlass() { 18 | } 19 | 20 | ObjectKlass *ObjectKlass::get_instance() { 21 | if (instance == NULL) 22 | instance = new ObjectKlass(); 23 | 24 | return instance; 25 | } 26 | 27 | void HiObject::print() { 28 | klass()->print(this); 29 | } 30 | 31 | HiObject *HiObject::greater(HiObject *rhs) { 32 | return klass()->greater(this, rhs); 33 | } 34 | 35 | HiObject *HiObject::add(HiObject *rhs) { 36 | return klass()->add(this, rhs); 37 | } 38 | 39 | HiObject *HiObject::sub(HiObject *rhs) { 40 | return klass()->sub(this, rhs); 41 | } 42 | 43 | HiObject *HiObject::mul(HiObject *rhs) { 44 | return klass()->mul(this, rhs); 45 | } 46 | 47 | HiObject *HiObject::div(HiObject *rhs) { 48 | return klass()->div(this, rhs); 49 | } 50 | 51 | HiObject *HiObject::mod(HiObject *rhs) { 52 | return klass()->mod(this, rhs); 53 | } 54 | 55 | HiObject *HiObject::less(HiObject *rhs) { 56 | return klass()->less(this, rhs); 57 | } 58 | 59 | HiObject *HiObject::equal(HiObject *rhs) { 60 | return klass()->equal(this, rhs); 61 | } 62 | 63 | HiObject *HiObject::not_equal(HiObject *rhs) { 64 | return klass()->not_equal(this, rhs); 65 | } 66 | 67 | HiObject *HiObject::ge(HiObject *rhs) { 68 | return klass()->ge(this, rhs); 69 | } 70 | 71 | HiObject *HiObject::le(HiObject *rhs) { 72 | return klass()->le(this, rhs); 73 | } 74 | 75 | HiObject *HiObject::getattr(HiObject *x) { 76 | return klass()->getattr(this, x); 77 | } 78 | 79 | HiObject *HiObject::setattr(HiObject *x, HiObject *y) { 80 | return klass()->setattr(this, x, y); 81 | } 82 | 83 | void HiObject::init_dict() { 84 | _obj_dict = new HiDict(); 85 | } 86 | 87 | HiObject *HiObject::subscr(HiObject *x) { 88 | return klass()->subscr(this, x); 89 | } 90 | 91 | HiObject *HiObject::contains(HiObject *x) { 92 | return klass()->contains(this, x); 93 | } 94 | 95 | void HiObject::store_subscr(HiObject *x, HiObject *y) { 96 | return klass()->store_subscr(this, x, y); 97 | } 98 | 99 | void HiObject::del_subscr(HiObject *x) { 100 | return klass()->del_subscr(this, x); 101 | } 102 | 103 | HiObject *HiObject::iter() { 104 | return klass()->iter(this); 105 | } 106 | 107 | HiObject *HiObject::next() { 108 | return klass()->next(this); 109 | } 110 | 111 | HiObject *HiObject::len() { 112 | return klass()->len(this); 113 | } 114 | 115 | void *HiObject::operator new(size_t size) { 116 | return Universe::heap->allocate(size); 117 | } 118 | 119 | TypeKlass *TypeKlass::instance = NULL; 120 | 121 | TypeKlass *TypeKlass::get_instance() { 122 | if (instance == NULL) 123 | instance = new TypeKlass(); 124 | 125 | return instance; 126 | } 127 | 128 | void TypeKlass::print(HiObject *obj) { 129 | assert(obj->klass() == (Klass *) this); 130 | printf("own_klass(); 132 | 133 | HiDict *attr_dict = own_klass->klass_dict(); 134 | if (attr_dict) { 135 | HiObject *mod = attr_dict->get((HiObject *) StringTable::get_instance()->mod_str); 136 | if (mod != Universe::HiNone) { 137 | mod->print(); 138 | printf("."); 139 | } 140 | } 141 | 142 | own_klass->name()->print(); 143 | printf("'>"); 144 | } 145 | 146 | HiObject *TypeKlass::setattr(HiObject *x, HiObject *y, HiObject *z) { 147 | HiTypeObject *type_obj = (HiTypeObject *) x; 148 | type_obj->own_klass()->klass_dict()->put(y, z); 149 | return Universe::HiNone; 150 | } 151 | 152 | HiTypeObject::HiTypeObject() { 153 | set_klass(TypeKlass::get_instance()); 154 | } 155 | 156 | size_t TypeKlass::size() { 157 | return sizeof(HiTypeObject); 158 | } 159 | 160 | void HiTypeObject::set_own_klass(Klass *k) { 161 | _own_klass = k; 162 | k->set_type_object(this); 163 | } 164 | 165 | void TypeKlass::oops_do(OopClosure *f, HiObject *obj) { 166 | // do nothing since HiTypeObject refers no oop. 167 | } 168 | 169 | void HiObject::oops_do(OopClosure *closure) { 170 | // object does not know who to visit, klass know 171 | closure->do_oop((HiObject **) &_obj_dict); 172 | klass()->oops_do(closure, this); 173 | } 174 | 175 | size_t HiObject::size() { 176 | return klass()->size(); 177 | } 178 | 179 | char *HiObject::new_address() { 180 | if ((_mark_word & 0x1) == 0x1) { 181 | return (char *) (_mark_word & ((long) -8)); 182 | } 183 | 184 | return NULL; 185 | } 186 | 187 | void HiObject::set_new_address(char *addr) { 188 | if (!addr) { 189 | return; 190 | } 191 | 192 | _mark_word = ((long long) addr) | 0x1; 193 | } 194 | -------------------------------------------------------------------------------- /object/hiObject.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/14. 3 | // 4 | 5 | #ifndef PYTHONVM_HIOBJECT_HPP 6 | #define PYTHONVM_HIOBJECT_HPP 7 | 8 | #include "klass.hpp" 9 | 10 | class HiString; 11 | 12 | class ObjectKlass : public Klass { 13 | private: 14 | ObjectKlass(); 15 | static ObjectKlass *instance; 16 | 17 | public: 18 | static ObjectKlass *get_instance(); 19 | // TODO oops? 20 | }; 21 | 22 | class HiObject { 23 | private: 24 | long _mark_word; 25 | Klass *_klass; 26 | HiDict *_obj_dict = NULL; 27 | 28 | public: 29 | Klass *klass() { 30 | assert(_klass != NULL); 31 | return _klass; 32 | } 33 | 34 | void set_klass(Klass *x) { _klass = x; } 35 | 36 | void print(); 37 | 38 | HiObject *add(HiObject *x); 39 | HiObject *sub(HiObject *x); 40 | HiObject *mul(HiObject *x); 41 | HiObject *div(HiObject *x); 42 | HiObject *mod(HiObject *x); 43 | 44 | HiObject *greater(HiObject *x); 45 | HiObject *less(HiObject *x); 46 | HiObject *equal(HiObject *x); 47 | HiObject *not_equal(HiObject *x); 48 | HiObject *ge(HiObject *x); 49 | HiObject *le(HiObject *x); 50 | 51 | HiObject *getattr(HiObject *x); 52 | HiObject *setattr(HiObject *x, HiObject *y); 53 | 54 | HiObject *subscr(HiObject *x); 55 | HiObject *contains(HiObject *x); 56 | void store_subscr(HiObject *x, HiObject *y); 57 | void del_subscr(HiObject *x); 58 | 59 | HiObject *iter(); 60 | HiObject *next(); 61 | HiObject *len(); 62 | 63 | HiDict *obj_dict() { return _obj_dict; } 64 | void set_obj_dict(HiDict *x) { _obj_dict = x; } 65 | void init_dict(); 66 | 67 | void *operator new(size_t size); 68 | 69 | // interfaces for GC. 70 | void oops_do(OopClosure *closure); 71 | size_t size(); 72 | char *new_address(); 73 | void set_new_address(char *addr); 74 | }; 75 | 76 | /** 77 | * Meta klass for object system 78 | */ 79 | class TypeKlass : public Klass { 80 | private: 81 | TypeKlass() {} 82 | 83 | static TypeKlass *instance; 84 | 85 | public: 86 | static TypeKlass *get_instance(); 87 | 88 | virtual void print(HiObject *obj); 89 | 90 | virtual HiObject *setattr(HiObject *x, HiObject *y, HiObject *z); 91 | 92 | virtual size_t size(); 93 | 94 | virtual void oops_do(OopClosure *f, HiObject *obj); 95 | }; 96 | 97 | class HiTypeObject : public HiObject { 98 | private: 99 | Klass *_own_klass; 100 | 101 | public: 102 | HiTypeObject(); 103 | 104 | void set_own_klass(Klass *k); 105 | 106 | Klass *own_klass() { return _own_klass; } 107 | }; 108 | 109 | #endif //PYTHONVM_HIOBJECT_HPP 110 | -------------------------------------------------------------------------------- /object/hiString.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/14. 3 | // 4 | 5 | #include 6 | #include 7 | 8 | #include "object/hiString.hpp" 9 | #include "object/hiInteger.hpp" 10 | #include "object/hiDict.hpp" 11 | #include "runtime/universe.hpp" 12 | #include "runtime/functionObject.hpp" 13 | #include "memory/heap.hpp" 14 | #include "memory/oopClosure.hpp" 15 | 16 | StringKlass *StringKlass::instance = NULL; 17 | 18 | StringKlass *StringKlass::get_instance() { 19 | if (instance == NULL) 20 | instance = new StringKlass(); 21 | 22 | return instance; 23 | } 24 | 25 | StringKlass::StringKlass() { 26 | } 27 | 28 | void StringKlass::initialize() { 29 | (new HiTypeObject())->set_own_klass(this); 30 | 31 | HiDict *klass_dict = new HiDict(); 32 | klass_dict->put(new HiString("upper"), new FunctionObject(string_upper)); 33 | klass_dict->put(new HiString("join"), new FunctionObject(string_join)); 34 | set_klass_dict(klass_dict); 35 | 36 | set_name(new HiString("str")); 37 | add_super(ObjectKlass::get_instance()); 38 | (new HiTypeObject())->set_own_klass(this); 39 | } 40 | 41 | HiObject *StringKlass::equal(HiObject *x, HiObject *y) { 42 | if (x->klass() != y->klass()) 43 | return Universe::HiFalse; 44 | 45 | HiString *sx = (HiString *) x; 46 | HiString *sy = (HiString *) y; 47 | 48 | assert(sx && sx->klass() == (Klass *) this); 49 | assert(sy && sy->klass() == (Klass *) this); 50 | 51 | if (sx->length() != sy->length()) 52 | return Universe::HiFalse; 53 | 54 | for (int i = 0; i < sx->length(); i++) { 55 | if (sx->value()[i] != sy->value()[i]) 56 | return Universe::HiFalse; 57 | } 58 | 59 | return Universe::HiTrue; 60 | } 61 | 62 | HiString::HiString(const char *x) { 63 | _length = strlen(x); 64 | // _value = new char[_length]; 65 | _value = (char *) Universe::heap->allocate(_length); 66 | strcpy(_value, x); 67 | 68 | set_klass(StringKlass::get_instance()); 69 | } 70 | 71 | HiString::HiString(const char *x, const int length) { 72 | _length = length; 73 | // _value = new char[length]; 74 | _value = (char *) Universe::heap->allocate(_length); 75 | 76 | // do not use strcpy here, since '\0' is allowed. 77 | for (int i = 0; i < length; ++i) { 78 | _value[i] = x[i]; 79 | } 80 | 81 | set_klass(StringKlass::get_instance()); 82 | } 83 | 84 | HiString::HiString(const int length) { 85 | _length = length; 86 | // _value = new char[length]; 87 | _value = (char *) Universe::heap->allocate(_length + 1); 88 | set_klass(StringKlass::get_instance()); 89 | } 90 | 91 | void StringKlass::print(HiObject *obj) { 92 | HiString *str_obj = (HiString *) obj; 93 | assert(str_obj && str_obj->klass() == (Klass *) this); 94 | 95 | for (int i = 0; i < str_obj->length(); i++) { 96 | printf("%c", str_obj->value()[i]); 97 | } 98 | } 99 | 100 | HiObject *StringKlass::add(HiObject *x, HiObject *y) { 101 | assert(x && x->klass() == this); 102 | assert(y && y->klass() == this); 103 | 104 | HiString *sx = (HiString *) x; 105 | HiString *sy = (HiString *) y; 106 | 107 | HiString *sz = new HiString(sx->length() + sy->length()); 108 | 109 | memcpy(sz->_value, sx->_value, sx->length()); 110 | memcpy(sz->_value + sx->length(), 111 | sy->_value, 112 | sy->length()); 113 | 114 | sz->set(sx->length() + sy->length(), '\0'); 115 | 116 | return sz; 117 | } 118 | 119 | HiObject *StringKlass::len(HiObject *x) { 120 | return new HiInteger(((HiString *) x)->length()); 121 | } 122 | 123 | HiObject *StringKlass::allocate_instance(HiObject *callable, ArrayList *args) { 124 | if (!args || args->length() == 0) { 125 | return new HiString(""); 126 | } else { 127 | return NULL; 128 | } 129 | } 130 | 131 | HiObject *StringKlass::less(HiObject *x, HiObject *y) { 132 | HiString *sx = (HiString *) x; 133 | assert(sx && (sx->klass() == (Klass *) this)); 134 | 135 | if (x->klass() != y->klass()) { 136 | if (Klass::compare_klass(x->klass(), y->klass()) < 0) 137 | return Universe::HiTrue; 138 | else 139 | return Universe::HiFalse; 140 | } 141 | 142 | HiString *sy = (HiString *) y; 143 | assert(sy && (sy->klass() == (Klass *) this)); 144 | 145 | int len = sx->length() < sy->length() ? 146 | sx->length() : sy->length(); 147 | 148 | for (int i = 0; i < len; i++) { 149 | if (sx->value()[i] < sy->value()[i]) 150 | return Universe::HiTrue; 151 | else if (sx->value()[i] > sy->value()[i]) 152 | return Universe::HiFalse; 153 | } 154 | 155 | if (sx->length() < sy->length()) { 156 | return Universe::HiTrue; 157 | } 158 | 159 | return Universe::HiFalse; 160 | } 161 | 162 | HiObject *StringKlass::subscr(HiObject *x, HiObject *y) { 163 | assert(x && x->klass() == (Klass *) this); 164 | assert(y && y->klass() == (Klass *) IntegerKlass::get_instance()); 165 | 166 | HiString *sx = (HiString *) x; 167 | HiInteger *iy = (HiInteger *) y; 168 | 169 | return new HiString(&(sx->value()[iy->value()]), 1); 170 | } 171 | 172 | HiObject *StringKlass::contains(HiObject *x, HiObject *y) { 173 | HiString *sx = (HiString *) x; 174 | HiString *sy = (HiString *) y; 175 | assert(sx && sx->klass() == (Klass *) this); 176 | assert(sy && sy->klass() == (Klass *) this); 177 | 178 | for (int i = 0; i < sx->length(); ++i) { 179 | if (sx->length() - i < sy->length()) { 180 | return Universe::HiFalse; 181 | } 182 | 183 | for (int j = 0; j < sy->length(); ++j) { 184 | if (j == sy->length() - 1) { 185 | return Universe::HiTrue; 186 | } 187 | 188 | if (sx->value()[i + j] != sy->value()[j]) { 189 | break; 190 | } 191 | } 192 | } 193 | 194 | return Universe::HiFalse; 195 | } 196 | 197 | size_t StringKlass::size() { 198 | return sizeof(HiString); 199 | } 200 | 201 | void StringKlass::oops_do(OopClosure *closure, HiObject *obj) { 202 | HiString *str_obj = (HiString *) obj; 203 | assert(str_obj && str_obj->klass() == (Klass *) this); 204 | 205 | closure->do_raw_mem(str_obj->value_address(), str_obj->length()); 206 | } 207 | 208 | 209 | HiString *HiString::join(HiObject *iterable) { 210 | int total = 0; 211 | 212 | HiObject *iter = iterable->iter(); 213 | HiObject *str = iter->next(); 214 | 215 | if (str == NULL) 216 | return new HiString(""); 217 | 218 | total += ((HiString *) str)->length(); 219 | while ((str = iter->next()) != NULL) { 220 | total += _length; 221 | total += ((HiString *) str)->length(); 222 | } 223 | 224 | HiString *sz = new HiString(total); 225 | total = 0; 226 | 227 | iter = iterable->iter(); 228 | str = iter->next(); 229 | HiString *sobj = (HiString *) str; 230 | 231 | memcpy(sz->_value, sobj->_value, sobj->length()); 232 | total += ((HiString *) str)->length(); 233 | while ((str = iter->next()) != NULL) { 234 | HiString *sobj = (HiString *) str; 235 | memcpy(sz->_value + total, _value, _length); 236 | total += _length; 237 | memcpy(sz->_value + total, sobj->_value, sobj->length()); 238 | total += sobj->_length; 239 | } 240 | 241 | return sz; 242 | } 243 | 244 | HiObject *string_join(ObjList args) { 245 | HiString *arg0 = (HiString *) (args->get(0)); 246 | return arg0->join(args->get(1)); 247 | } -------------------------------------------------------------------------------- /object/hiString.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/14. 3 | // 4 | 5 | #ifndef PYTHONVM_HISTRING_HPP 6 | #define PYTHONVM_HISTRING_HPP 7 | 8 | #include "hiObject.hpp" 9 | 10 | class StringKlass : public Klass { 11 | private: 12 | StringKlass(); 13 | 14 | static StringKlass *instance; 15 | 16 | public: 17 | static StringKlass *get_instance(); 18 | 19 | void initialize(); 20 | 21 | virtual HiObject *equal(HiObject *x, HiObject *y); 22 | 23 | virtual void print(HiObject *obj); 24 | 25 | virtual HiObject *add(HiObject *x, HiObject *y); 26 | 27 | virtual HiObject *less(HiObject *x, HiObject *y); 28 | 29 | virtual HiObject *subscr(HiObject *x, HiObject *y); 30 | 31 | virtual HiObject *contains(HiObject *x, HiObject *y); 32 | 33 | virtual HiObject *len(HiObject *x); 34 | 35 | virtual HiObject *allocate_instance(HiObject *callable, ArrayList *args); 36 | 37 | virtual size_t size(); 38 | 39 | virtual void oops_do(OopClosure *closure, HiObject *obj); 40 | }; 41 | 42 | class HiString : public HiObject { 43 | friend class StringKlass; 44 | 45 | private: 46 | char *_value; 47 | int _length; 48 | 49 | public: 50 | HiString(const char *x); 51 | 52 | HiString(const char *x, const int length); 53 | 54 | HiString(const int len); 55 | 56 | const char *value() { 57 | return _value; 58 | } 59 | 60 | char **value_address() { 61 | return &_value; 62 | } 63 | 64 | int length() { 65 | return _length; 66 | } 67 | 68 | void set(int i, char x) { 69 | _value[i] = x; 70 | } 71 | 72 | HiString *join(HiObject *iterable); 73 | }; 74 | 75 | HiObject *string_upper(ObjList args); 76 | 77 | HiObject *string_join(ObjList args); 78 | 79 | #endif //PYTHONVM_HISTRING_HPP 80 | -------------------------------------------------------------------------------- /object/klass.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/16. 3 | // 4 | 5 | #include "klass.hpp" 6 | #include "runtime/interpreter.hpp" 7 | #include "runtime/stringTable.hpp" 8 | #include "runtime/functionObject.hpp" 9 | #include "runtime/universe.hpp" 10 | #include "object/hiObject.hpp" 11 | #include "object/hiInteger.hpp" 12 | #include "object/hiString.hpp" 13 | #include "object/hiDict.hpp" 14 | #include "object/hiList.hpp" 15 | #include "memory/heap.hpp" 16 | #include "memory/oopClosure.hpp" 17 | 18 | #define ST(x) StringTable::get_instance()->STR(x) 19 | #define STR(x) x##_str 20 | 21 | Klass::Klass() { 22 | Universe::klasses->add(this); 23 | _klass_dict = NULL; 24 | _name = NULL; 25 | _super = NULL; 26 | _mro = NULL; 27 | } 28 | 29 | int Klass::compare_klass(Klass *x, Klass *y) { 30 | if (x == y) { 31 | return 0; 32 | } 33 | 34 | if (x == IntegerKlass::get_instance()) { 35 | return -1; 36 | } else if (y == IntegerKlass::get_instance()) { 37 | return 1; 38 | } 39 | 40 | if (x->name()->less(y->name()) == (HiObject *) Universe::HiTrue) { 41 | return -1; 42 | } else { 43 | return 1; 44 | } 45 | } 46 | 47 | HiObject *Klass::create_klass(HiObject *x, HiObject *supers, HiObject *name) { 48 | assert(x->klass() == (Klass *) DictKlass::get_instance()); 49 | assert(supers->klass() == (Klass *) ListKlass::get_instance()); 50 | assert(name->klass() == (Klass *) StringKlass::get_instance()); 51 | 52 | Klass *new_klass = new Klass(); 53 | HiDict *klass_dict = (HiDict *) x; 54 | HiList *supers_list = (HiList *) supers; 55 | 56 | new_klass->set_klass_dict(klass_dict); 57 | new_klass->set_name((HiString *) name); 58 | new_klass->set_super_list(supers_list); 59 | new_klass->order_supers(); 60 | 61 | HiTypeObject *type_obj = new HiTypeObject(); 62 | type_obj->set_own_klass(new_klass); 63 | 64 | return type_obj; 65 | } 66 | 67 | void Klass::print(HiObject *x) { 68 | HiObject *meth_repr = get_klass_attr(x, ST(repr)); 69 | if (meth_repr != Universe::HiNone) { 70 | Interpreter::get_instance()->call_virtual(meth_repr, NULL)->print(); 71 | return; 72 | } 73 | 74 | printf("klass()->name()->print(); 76 | printf(", at %p>", x); 77 | } 78 | 79 | HiObject *Klass::allocate_instance(HiObject *callable, ArrayList *args) { 80 | HiObject *instance = new HiObject(); 81 | instance->set_klass(((HiTypeObject *) callable)->own_klass()); 82 | HiObject *constructor = instance->getattr(StringTable::get_instance()->init_str); 83 | if (constructor != Universe::HiNone) { 84 | Interpreter::get_instance()->call_virtual(constructor, args); 85 | } 86 | 87 | return instance; 88 | } 89 | 90 | HiObject *Klass::find_and_call(HiObject *lhs, ObjList args, HiObject *func_name) { 91 | HiObject *func = lhs->getattr(func_name); 92 | if (func != Universe::HiNone) { 93 | return Interpreter::get_instance()->call_virtual(func, args); 94 | } 95 | 96 | printf("class "); 97 | lhs->klass()->name()->print(); 98 | printf(" Error : unsupport operation for class "); 99 | assert(false); 100 | return Universe::HiNone; 101 | } 102 | 103 | HiObject *Klass::find_in_parents(HiObject *x, HiObject *y) { 104 | HiObject *result = Universe::HiNone; 105 | result = x->klass()->klass_dict()->get(y); 106 | 107 | if (result != Universe::HiNone) { 108 | return result; 109 | } 110 | 111 | // find attribute in all parents. 112 | if (x->klass()->mro() == NULL) { 113 | return result; 114 | } 115 | 116 | for (int i = 0; i < x->klass()->mro()->size(); i++) { 117 | result = ((HiTypeObject *) (x->klass()->mro()->get(i)))->own_klass()->klass_dict()->get(y); 118 | if (result != Universe::HiNone) { 119 | return result; 120 | } 121 | } 122 | 123 | return result; 124 | } 125 | 126 | HiObject *Klass::add(HiObject *lhs, HiObject *rhs) { 127 | ObjList args = new ArrayList(); 128 | args->add(rhs); 129 | return find_and_call(lhs, args, ST(add)); 130 | } 131 | 132 | HiObject *Klass::len(HiObject *x) { 133 | return find_and_call(x, NULL, ST(len)); 134 | } 135 | 136 | HiObject *Klass::subscr(HiObject *x, HiObject *y) { 137 | ObjList args = new ArrayList(); 138 | args->add(y); 139 | return find_and_call(x, args, ST(getitem)); 140 | } 141 | 142 | void Klass::store_subscr(HiObject *x, HiObject *y, HiObject *z) { 143 | ObjList args = new ArrayList(); 144 | args->add(y); 145 | args->add(z); 146 | find_and_call(x, args, ST(setitem)); 147 | } 148 | 149 | HiObject *Klass::getattr(HiObject *x, HiObject *y) { 150 | HiObject *func = find_in_parents(x, ST(getattr)); 151 | if (func->klass() == FunctionKlass::get_instance()) { 152 | func = new MethodObject((FunctionObject *) func, x); 153 | ObjList args = new ArrayList(); 154 | args->add(y); 155 | return Interpreter::get_instance()->call_virtual(func, args); 156 | } 157 | 158 | HiObject *result = Universe::HiNone; 159 | 160 | if (x->obj_dict() != NULL) { 161 | result = x->obj_dict()->get(y); 162 | if (result != Universe::HiNone) { 163 | return result; 164 | } 165 | } 166 | 167 | return get_klass_attr(x, y); 168 | } 169 | 170 | HiObject *Klass::setattr(HiObject *x, HiObject *y, HiObject *z) { 171 | HiObject *func = x->klass()->klass_dict()->get(ST(setattr)); 172 | if (func->klass() == FunctionKlass::get_instance()) { 173 | func = new MethodObject((FunctionObject *) func, x); 174 | ObjList args = new ArrayList(); 175 | args->add(y); 176 | args->add(z); 177 | return Interpreter::get_instance()->call_virtual(func, args); 178 | } 179 | 180 | if (x->obj_dict() == NULL) { 181 | x->init_dict(); 182 | } 183 | 184 | x->obj_dict()->put(y, z); 185 | return Universe::HiNone; 186 | } 187 | 188 | HiObject *Klass::get_klass_attr(HiObject *x, HiObject *y) { 189 | HiObject *result = Universe::HiNone; 190 | 191 | result = find_in_parents(x, y); 192 | if (MethodObject::is_function(result)) { 193 | result = new MethodObject((FunctionObject *) result, x); 194 | } 195 | 196 | return result; 197 | } 198 | 199 | void Klass::add_super(Klass *klass) { 200 | if (_super == NULL) { 201 | _super = new HiList(); 202 | } 203 | 204 | _super->append(klass->type_object()); 205 | } 206 | 207 | HiTypeObject *Klass::super() { 208 | if (_super == NULL) { 209 | return NULL; 210 | } 211 | 212 | if (_super->size() <= 0) { 213 | return NULL; 214 | } 215 | 216 | return (HiTypeObject *) _super->get(0); 217 | } 218 | 219 | void Klass::order_supers() { 220 | if (_super == NULL) { 221 | return; 222 | } 223 | 224 | if (_mro == NULL) { 225 | _mro = new HiList(); 226 | } 227 | 228 | int cur = -1; 229 | for (int i = 0; i < _super->size(); ++i) { 230 | HiTypeObject *tp_obj = (HiTypeObject *) (_super->get(i)); 231 | Klass *k = tp_obj->own_klass(); 232 | _mro->append(tp_obj); 233 | if (k->mro() == NULL) { 234 | continue; 235 | } 236 | 237 | for (int j = 0; j < k->mro()->size(); ++j) { 238 | HiTypeObject *tp_obj = (HiTypeObject *) (k->mro()->get(j)); 239 | int index = _mro->index(tp_obj); 240 | if (index < cur) { 241 | printf("Error: method resolution order conflicts.\n"); 242 | assert(false); 243 | } 244 | 245 | cur = index; 246 | if (index >= 0) { 247 | _mro->delete_index(index); 248 | } 249 | _mro->append(tp_obj); 250 | } 251 | } 252 | 253 | printf("%s's mro is ", _name->value()); 254 | for (int i = 0; i < _mro->size(); i++) { 255 | HiTypeObject *tp_obj = (HiTypeObject *) (_mro->get(i)); 256 | Klass *k = tp_obj->own_klass(); 257 | printf("%s, ", k->name()->value()); 258 | } 259 | printf("\n"); 260 | } 261 | 262 | void *Klass::operator new(size_t size) { 263 | return Universe::heap->allocate_meta(size); 264 | } 265 | 266 | size_t Klass::size() { 267 | return sizeof(HiObject); 268 | } 269 | 270 | HiObject *Klass::iter(HiObject *x) { 271 | return find_and_call(x, NULL, ST(iter)); 272 | } 273 | 274 | HiObject *Klass::next(HiObject *x) { 275 | return find_and_call(x, NULL, ST(next)); 276 | } 277 | 278 | // this function will visit all children 279 | void Klass::oops_do(OopClosure *closure, HiObject *obj) { 280 | printf("warning: klass oops_do for "); 281 | _name->print(); 282 | printf("\n"); 283 | } 284 | 285 | void Klass::oops_do(OopClosure *closure) { 286 | closure->do_oop((HiObject **) &_super); 287 | closure->do_oop((HiObject **) &_mro); 288 | closure->do_oop((HiObject **) &_name); 289 | closure->do_oop((HiObject **) &_klass_dict); 290 | closure->do_oop((HiObject **) &_type_object); 291 | } 292 | -------------------------------------------------------------------------------- /object/klass.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/16. 3 | // 4 | 5 | #ifndef PYTHONVM_KLASS_HPP 6 | #define PYTHONVM_KLASS_HPP 7 | 8 | #include 9 | #include 10 | #include "util/arrayList.hpp" 11 | 12 | class HiTypeObject; 13 | class HiObject; 14 | class HiString; 15 | class HiDict; 16 | class HiList; 17 | class OopClosure; 18 | 19 | class Klass { 20 | private: 21 | HiList *_super; 22 | HiList *_mro; 23 | HiTypeObject *_type_object; 24 | HiString * _name; 25 | HiDict* _klass_dict; 26 | 27 | HiObject *find_and_call(HiObject *x, ObjList args, HiObject *func_name); 28 | HiObject *find_in_parents(HiObject *x, HiObject *y); 29 | public: 30 | Klass(); 31 | 32 | static HiObject *create_klass(HiObject *x, HiObject *supers, HiObject *name); 33 | 34 | static int compare_klass(Klass* x, Klass* y); 35 | 36 | void set_type_object(HiTypeObject *x) { _type_object = x; } 37 | HiTypeObject *type_object() { return _type_object; } 38 | 39 | void add_super(Klass *x); 40 | HiTypeObject *super(); 41 | void order_supers(); 42 | 43 | void set_super_list(HiList *x) { _super = x; } 44 | HiList *mro() { return _mro; } 45 | 46 | void set_name(HiString * x) { _name = x; } 47 | HiString *name() const { return _name; } 48 | 49 | void set_klass_dict(HiDict *dict) { _klass_dict = dict; } 50 | HiDict *klass_dict() { return _klass_dict; } 51 | 52 | virtual void print(HiObject *obj); 53 | 54 | virtual HiObject* greater (HiObject* x, HiObject* y) { return 0; } 55 | virtual HiObject* less (HiObject* x, HiObject* y) { return 0; } 56 | virtual HiObject* equal (HiObject* x, HiObject* y) { return 0; } 57 | virtual HiObject* not_equal(HiObject* x, HiObject* y) { return 0; } 58 | virtual HiObject* ge (HiObject* x, HiObject* y) { return 0; } 59 | virtual HiObject* le (HiObject* x, HiObject* y) { return 0; } 60 | 61 | virtual HiObject* add(HiObject* x, HiObject* y); 62 | // TODO operator overload 63 | virtual HiObject* sub(HiObject* x, HiObject* y) { return 0; } 64 | virtual HiObject* mul(HiObject* x, HiObject* y) { return 0; } 65 | virtual HiObject* div(HiObject* x, HiObject* y) { return 0; } 66 | virtual HiObject* mod(HiObject* x, HiObject* y) { return 0; } 67 | 68 | virtual HiObject *subscr(HiObject *x, HiObject *y); 69 | virtual void store_subscr(HiObject *x, HiObject *y, HiObject *z); 70 | virtual void del_subscr(HiObject *x, HiObject *y) { return;} 71 | 72 | virtual HiObject *len(HiObject *x); 73 | 74 | virtual HiObject *contains(HiObject *x, HiObject *y) { return 0; } 75 | 76 | virtual HiObject *getattr(HiObject *x, HiObject *y); 77 | virtual HiObject *setattr(HiObject *x, HiObject *y, HiObject *z); 78 | 79 | virtual HiObject *next (HiObject* x); 80 | virtual HiObject *iter (HiObject* x); 81 | 82 | virtual HiObject *allocate_instance(HiObject* callable, ArrayList *args); 83 | virtual HiObject *get_klass_attr(HiObject *x, HiObject *y); 84 | 85 | void* operator new(size_t size); 86 | 87 | // gc interfaces 88 | // this is for objects of this type. 89 | virtual void oops_do(OopClosure* closure, HiObject* obj); 90 | // for klass itself only. 91 | virtual void oops_do(OopClosure* closure); 92 | 93 | virtual size_t size(); 94 | }; 95 | 96 | #endif //PYTHONVM_KLASS_HPP 97 | -------------------------------------------------------------------------------- /runtime/cellObject.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/28. 3 | // 4 | 5 | #include "runtime/cellObject.hpp" 6 | #include "object/hiList.hpp" 7 | #include "object/hiDict.hpp" 8 | #include "object/hiString.hpp" 9 | #include "memory/oopClosure.hpp" 10 | 11 | CellKlass *CellKlass::_instance = NULL; 12 | 13 | CellKlass *CellKlass::get_instance() { 14 | if (_instance == NULL) { 15 | _instance = new CellKlass(); 16 | } 17 | 18 | return _instance; 19 | } 20 | 21 | CellKlass::CellKlass() { 22 | set_klass_dict(new HiDict()); 23 | set_name(new HiString("cell")); 24 | } 25 | 26 | CellObject::CellObject(HiList *t, int i) : 27 | _table(t), 28 | _index(i) { 29 | set_klass(CellKlass::get_instance()); 30 | } 31 | 32 | HiObject *CellObject::value() { 33 | return _table->get(_index); 34 | } 35 | 36 | size_t CellKlass::size() { 37 | return sizeof(CellKlass); 38 | } 39 | 40 | void CellKlass::oops_do(OopClosure *f, HiObject *obj) { 41 | CellObject *co = (CellObject *) obj; 42 | f->do_oop((HiObject **) &co->_table); 43 | } 44 | -------------------------------------------------------------------------------- /runtime/cellObject.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/28. 3 | // 4 | 5 | #ifndef PYTHONVM_CELLOBJECT_HPP 6 | #define PYTHONVM_CELLOBJECT_HPP 7 | 8 | #include "object/klass.hpp" 9 | #include "object/hiObject.hpp" 10 | 11 | class CellKlass : public Klass { 12 | private: 13 | CellKlass(); 14 | 15 | static CellKlass *_instance; 16 | 17 | public: 18 | static CellKlass *get_instance(); 19 | 20 | virtual size_t size(); 21 | virtual void oops_do(OopClosure *f, HiObject *obj); 22 | }; 23 | 24 | // 这种方式STORE_DEREF修改后仍然可见 25 | class CellObject : public HiObject { 26 | friend class CellKlass; 27 | 28 | private: 29 | HiList *_table; 30 | int _index; 31 | 32 | public: 33 | CellObject(HiList *l, int i); 34 | 35 | HiObject *value(); 36 | }; 37 | 38 | #endif //PYTHONVM_CELLOBJECT_HPP 39 | -------------------------------------------------------------------------------- /runtime/frameObject.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/16. 3 | // 4 | 5 | #include "object/hiObject.hpp" 6 | #include "object/hiString.hpp" 7 | #include "object/hiObject.hpp" 8 | #include "object/hiDict.hpp" 9 | #include "runtime/frameObject.hpp" 10 | 11 | // this constructor is used for module only. 12 | FrameObject::FrameObject(CodeObject *codes) { 13 | _codes = codes; 14 | _consts = codes->_consts; 15 | _names = codes->_names; 16 | 17 | _locals = new HiDict(); 18 | _globals = _locals; 19 | _fast_locals = NULL; 20 | 21 | _stack = new HiList(); 22 | _loop_stack = new ArrayList(); 23 | 24 | _pc = 0; 25 | _sender = NULL; 26 | _entry_frame = false; 27 | } 28 | 29 | FrameObject::FrameObject(FunctionObject *func, ObjList args, int op_arg) { 30 | assert((args && op_arg != 0) || (args == NULL && op_arg == 0)); 31 | 32 | _codes = func->_func_code; 33 | _consts = _codes->_consts; 34 | _names = _codes->_names; 35 | 36 | _locals = new HiDict(); 37 | _globals = func->_globals; 38 | _fast_locals = new HiList(); 39 | 40 | // 形参数量 41 | const int argcnt = _codes->_argcount; 42 | const int na = op_arg & 0xff; 43 | const int nk = op_arg >> 8; 44 | int kw_pos = argcnt; 45 | 46 | if (func->_defaults) { 47 | int dft_num = func->_defaults->length(); 48 | int arg_num = _codes->_argcount; 49 | while (dft_num--) { 50 | _fast_locals->set(--arg_num, func->_defaults->get(dft_num)); 51 | } 52 | } 53 | 54 | // 扩展位置参数 55 | HiList *alist = NULL; 56 | HiDict *adict = NULL; 57 | 58 | if (argcnt < na) { 59 | int i = 0; 60 | for (; i < argcnt; i++) { 61 | _fast_locals->set(i, args->get(i)); 62 | } 63 | alist = new HiList(); 64 | for (; i < na; i++) { 65 | alist->append(args->get(i)); 66 | } 67 | } else { 68 | for (int i = 0; i < na; i++) { 69 | _fast_locals->set(i, args->get(i)); 70 | } 71 | } 72 | 73 | // 处理键参数 74 | for (int i = 0; i < nk; i++) { 75 | HiObject *key = args->get(na + i * 2); 76 | HiObject *val = args->get(na + i * 2 + 1); 77 | 78 | int index = _codes->_var_names->index(key); 79 | if (index >= 0) { 80 | _fast_locals->set(index, val); 81 | } else { 82 | if (adict == NULL) { 83 | adict = new HiDict(); 84 | } 85 | 86 | adict->put(key, val); 87 | } 88 | } 89 | 90 | // 存在扩展位置参数 91 | if (_codes->_flag & FunctionObject::CO_VARARGS) { 92 | if (alist == NULL) 93 | alist = new HiList(); 94 | _fast_locals->set(argcnt, alist); 95 | kw_pos += 1; 96 | } else { 97 | // give more parameters than need. 98 | if (alist != NULL) { 99 | printf("takes more extend parameters.\n"); 100 | assert(false); 101 | } 102 | } 103 | 104 | // 存在键参数 105 | if (_codes->_flag & FunctionObject::CO_VARKEYWORDS) { 106 | if (adict == NULL) 107 | adict = new HiDict(); 108 | 109 | _fast_locals->set(kw_pos, adict); 110 | } else { 111 | if (adict != NULL) { 112 | printf("takes more extend kw parameters.\n"); 113 | assert(false); 114 | } 115 | } 116 | 117 | _closure = NULL; 118 | ArrayList *cells = _codes->_cell_vars; 119 | if (cells && cells->size() > 0) { 120 | _closure = new HiList(); 121 | 122 | for (int i = 0; i < cells->size(); i++) { 123 | _closure->append(NULL); 124 | } 125 | } 126 | 127 | if (func->closure() && func->closure()->size() > 0) { 128 | if (_closure == NULL) 129 | _closure = func->closure(); 130 | else { 131 | _closure = (HiList *) _closure->add(func->closure()); 132 | } 133 | } 134 | 135 | _stack = new HiList(); 136 | _loop_stack = new ArrayList(); 137 | 138 | _pc = 0; 139 | _sender = NULL; 140 | _entry_frame = false; 141 | } 142 | 143 | int FrameObject::get_op_arg() { 144 | int byte1 = _codes->_bytecodes->value()[_pc++] & 0xff; 145 | int byte2 = _codes->_bytecodes->value()[_pc++] & 0xff; 146 | return byte2 << 8 | byte1; 147 | } 148 | 149 | unsigned char FrameObject::get_op_code() { 150 | return _codes->_bytecodes->value()[_pc++]; 151 | } 152 | 153 | bool FrameObject::has_more_codes() { 154 | return _pc < _codes->_bytecodes->length(); 155 | } 156 | 157 | HiObject *FrameObject::get_cell_from_parameter(int i) { 158 | HiObject *cell_name = _codes->_cell_vars->get(i); 159 | i = _codes->_var_names->index(cell_name); 160 | return _fast_locals->get(i); 161 | } 162 | 163 | int FrameObject::lineno() { 164 | return _codes->_lineno; 165 | } 166 | 167 | HiString *FrameObject::file_name() { 168 | return _codes->_file_name; 169 | } 170 | 171 | HiString *FrameObject::func_name() { 172 | return _codes->_co_name; 173 | } 174 | 175 | void FrameObject::oops_do(OopClosure *f) { 176 | f->do_array_list(&_consts); 177 | f->do_array_list(&_names); 178 | 179 | f->do_oop((HiObject **) &_globals); 180 | f->do_oop((HiObject **) &_locals); 181 | f->do_oop((HiObject **) &_fast_locals); 182 | f->do_oop((HiObject **) &_closure); 183 | f->do_oop((HiObject **) &_stack); 184 | 185 | f->do_oop((HiObject **) &_codes); 186 | 187 | if (_sender) { 188 | // sender is not in heap 189 | _sender->oops_do(f); 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /runtime/frameObject.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/16. 3 | // 4 | 5 | #ifndef PYTHONVM_FRAMEOBJECT_HPP 6 | #define PYTHONVM_FRAMEOBJECT_HPP 7 | 8 | #include 9 | #include "object/hiList.hpp" 10 | #include "code/codeObject.hpp" 11 | #include "util/map.hpp" 12 | #include "util/arrayList.hpp" 13 | #include "functionObject.hpp" 14 | 15 | class Block { 16 | public: 17 | unsigned char _type; 18 | unsigned int _target; 19 | int _level; 20 | 21 | Block() { 22 | _type = 0; 23 | _target = 0; 24 | _level = 0; 25 | } 26 | 27 | Block(unsigned char b_type, 28 | unsigned int b_target, 29 | int b_level) : 30 | _type(b_type), 31 | _target(b_target), 32 | _level(b_level) { 33 | } 34 | 35 | Block(const Block &b) { 36 | _type = b._type; 37 | _target = b._target; 38 | _level = b._level; 39 | } 40 | }; 41 | 42 | class FrameObject { 43 | public: 44 | FrameObject(CodeObject *codes); 45 | 46 | FrameObject(FunctionObject *func, ObjList args, int op_arg); 47 | 48 | HiList *_stack; 49 | ArrayList *_loop_stack; 50 | 51 | ArrayList *_consts; 52 | ArrayList *_names; 53 | 54 | HiDict *_locals; 55 | HiDict *_globals; 56 | HiList *_fast_locals; 57 | HiList *_closure; 58 | 59 | FrameObject *_sender; 60 | CodeObject *_codes; 61 | int _pc; 62 | // 标记是否cpp调用python产生的栈帧 63 | bool _entry_frame; 64 | 65 | public: 66 | void set_sender(FrameObject *x) { _sender = x; } 67 | 68 | FrameObject *sender() { return _sender; } 69 | 70 | void set_pc(int x) { _pc = x; } 71 | 72 | int get_pc() { return _pc; } 73 | 74 | void set_entry_frame(bool x) { _entry_frame = x; } 75 | 76 | bool is_entry_frame() { return _entry_frame; } 77 | 78 | bool is_first_frame() { return _sender == NULL; } 79 | 80 | HiList *stack() { return _stack; } 81 | 82 | ArrayList *loop_stack() { return _loop_stack; } 83 | 84 | ArrayList *consts() { return _consts; } 85 | 86 | ArrayList *names() { return _names; } 87 | 88 | HiDict *locals() { return _locals; } 89 | 90 | HiDict *globals() { return _globals; } 91 | 92 | HiList *fast_locals() { return _fast_locals; } 93 | 94 | HiList *closure() { return _closure; } 95 | 96 | HiObject *get_cell_from_parameter(int i); 97 | 98 | bool has_more_codes(); 99 | 100 | unsigned char get_op_code(); 101 | 102 | int get_op_arg(); 103 | 104 | HiString *file_name(); 105 | 106 | HiString *func_name(); 107 | 108 | int lineno(); 109 | 110 | void oops_do(OopClosure *f); 111 | }; 112 | 113 | #endif //PYTHONVM_FRAMEOBJECT_HPP 114 | -------------------------------------------------------------------------------- /runtime/functionObject.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/16. 3 | // 4 | 5 | #include "object/hiInteger.hpp" 6 | #include "object/hiString.hpp" 7 | #include "object/hiList.hpp" 8 | #include "object/hiDict.hpp" 9 | #include "runtime/universe.hpp" 10 | #include "runtime/functionObject.hpp" 11 | #include "memory/oopClosure.hpp" 12 | 13 | FunctionKlass *FunctionKlass::instance = NULL; 14 | 15 | FunctionKlass::FunctionKlass() { 16 | add_super(ObjectKlass::get_instance()); 17 | set_name(new HiString("function")); 18 | HiTypeObject *tp_obj = new HiTypeObject(); 19 | tp_obj->set_own_klass(this); 20 | } 21 | 22 | FunctionKlass *FunctionKlass::get_instance() { 23 | if (instance == NULL) 24 | instance = new FunctionKlass(); 25 | 26 | return instance; 27 | } 28 | 29 | void FunctionKlass::print(HiObject *obj) { 30 | printf("(obj); 32 | 33 | assert(fo && fo->klass() == (Klass *) this); 34 | fo->func_name()->print(); 35 | printf(">"); 36 | } 37 | 38 | size_t FunctionKlass::size() { 39 | return sizeof(FunctionKlass); 40 | } 41 | 42 | void FunctionKlass::oops_do(OopClosure *f, HiObject *obj) { 43 | FunctionObject *fo = (FunctionObject *) obj; 44 | assert(fo->klass() == (Klass *) this); 45 | 46 | f->do_oop((HiObject **) &fo->_func_code); 47 | f->do_oop((HiObject **) &fo->_func_name); 48 | f->do_oop((HiObject **) &fo->_globals); 49 | f->do_oop((HiObject **) &fo->_closure); 50 | f->do_array_list(&fo->_defaults); 51 | } 52 | 53 | FunctionObject::FunctionObject(HiObject *code_object) { 54 | CodeObject *co = (CodeObject *) code_object; 55 | 56 | _func_code = co; 57 | _func_name = co->_co_name; 58 | _flags = co->_flag; 59 | _globals = NULL; 60 | _closure = NULL; 61 | 62 | set_klass(FunctionKlass::get_instance()); 63 | } 64 | 65 | FunctionObject::FunctionObject(NativeFuncPointer nfp) { 66 | _func_code = NULL; 67 | _func_name = NULL; 68 | _flags = 0; 69 | _globals = NULL; 70 | _closure = NULL; 71 | _native_func = nfp; 72 | 73 | set_klass(NativeFunctionKlass::get_instance()); 74 | } 75 | 76 | void FunctionObject::set_default(ArrayList *defaults) { 77 | if (defaults == NULL) { 78 | _defaults = NULL; 79 | return; 80 | } 81 | 82 | _defaults = new ArrayList(defaults->length()); 83 | 84 | for (int i = 0; i < defaults->length(); i++) { 85 | _defaults->set(i, defaults->get(i)); 86 | } 87 | } 88 | 89 | HiObject *FunctionObject::call(ObjList args) { 90 | return (*_native_func)(args); 91 | } 92 | 93 | NativeFunctionKlass *NativeFunctionKlass::instance = NULL; 94 | 95 | NativeFunctionKlass *NativeFunctionKlass::get_instance() { 96 | if (instance == NULL) 97 | instance = new NativeFunctionKlass(); 98 | 99 | return instance; 100 | } 101 | 102 | NativeFunctionKlass::NativeFunctionKlass() { 103 | add_super(FunctionKlass::get_instance()); 104 | set_name(new HiString("native function")); 105 | HiTypeObject *tp_obj = new HiTypeObject(); 106 | tp_obj->set_own_klass(this); 107 | } 108 | 109 | size_t NativeFunctionKlass::size() { 110 | return sizeof(FunctionObject); 111 | } 112 | 113 | void NativeFunctionKlass::oops_do(OopClosure *f, HiObject *obj) { 114 | FunctionObject *fo = (FunctionObject *) obj; 115 | assert(fo->klass() == (Klass *) this); 116 | 117 | f->do_oop((HiObject **) &fo->_func_code); 118 | f->do_oop((HiObject **) &fo->_func_name); 119 | f->do_oop((HiObject **) &fo->_globals); 120 | f->do_oop((HiObject **) &fo->_closure); 121 | f->do_array_list(&fo->_defaults); 122 | } 123 | 124 | MethodKlass::MethodKlass() { 125 | add_super(FunctionKlass::get_instance()); 126 | set_name(new HiString("method")); 127 | HiTypeObject *tp_obj = new HiTypeObject(); 128 | tp_obj->set_own_klass(this); 129 | } 130 | 131 | MethodKlass *MethodKlass::instance = NULL; 132 | 133 | MethodKlass *MethodKlass::get_instance() { 134 | if (instance == NULL) 135 | instance = new MethodKlass(); 136 | 137 | return instance; 138 | } 139 | 140 | size_t MethodKlass::size() { 141 | return sizeof(MethodKlass); 142 | } 143 | 144 | void MethodKlass::oops_do(OopClosure *f, HiObject *obj) { 145 | MethodObject *mo = (MethodObject *) obj; 146 | assert(mo->klass() == (Klass *) this); 147 | 148 | f->do_oop((HiObject **) &mo->_owner); 149 | f->do_oop((HiObject **) &mo->_func); 150 | } 151 | 152 | bool MethodObject::is_function(HiObject *x) { 153 | Klass *k = x->klass(); 154 | if (k == (Klass *) FunctionKlass::get_instance()) { 155 | return true; 156 | } 157 | 158 | if (k->mro() == NULL) { 159 | return false; 160 | } 161 | 162 | for (int i = 0; i < k->mro()->size(); i++) { 163 | if (k->mro()->get(i) == 164 | FunctionKlass::get_instance()->type_object()) { 165 | return true; 166 | } 167 | } 168 | 169 | return false; 170 | } 171 | 172 | bool MethodObject::is_yield_function(HiObject *x) { 173 | Klass *k = x->klass(); 174 | if (k != (Klass *) FunctionKlass::get_instance()) { 175 | return false; 176 | } 177 | 178 | FunctionObject *fo = (FunctionObject *) x; 179 | return ((fo->flags() & FunctionObject::CO_GENERATOR) != 0); 180 | } 181 | 182 | HiObject *len(ObjList args) { 183 | return args->get(0)->len(); 184 | } 185 | 186 | HiObject *iter(ObjList args) { 187 | return args->get(0)->iter(); 188 | } 189 | 190 | HiObject *isinstance(ObjList args) { 191 | HiObject *x = args->get(0); 192 | HiObject *y = args->get(1); 193 | 194 | assert(y && y->klass() == TypeKlass::get_instance()); 195 | 196 | Klass *k = x->klass(); 197 | if (k->type_object() == y) 198 | return Universe::HiTrue; 199 | 200 | for (int i = 0; i < k->mro()->size(); i++) { 201 | if (k->mro()->get(i) == y) { 202 | return Universe::HiTrue; 203 | } 204 | } 205 | 206 | return Universe::HiFalse; 207 | } 208 | 209 | HiObject *type_of(ObjList args) { 210 | HiObject *arg0 = args->get(0); 211 | return arg0->klass()->type_object(); 212 | } 213 | 214 | HiObject *string_upper(ObjList args) { 215 | HiObject *arg0 = args->get(0); 216 | assert(arg0->klass() == StringKlass::get_instance()); 217 | 218 | HiString *str_obj = (HiString *) arg0; 219 | 220 | int length = str_obj->length(); 221 | if (length <= 0) 222 | return Universe::HiNone; 223 | 224 | char *v = new char[length]; 225 | char c; 226 | for (int i = 0; i < length; i++) { 227 | c = str_obj->value()[i]; 228 | if (c >= 'a' && c <= 'z') 229 | v[i] = c - 0x20; 230 | else 231 | v[i] = c; 232 | } 233 | 234 | HiString *s = new HiString(v, length); 235 | delete[]v; 236 | return s; 237 | } 238 | 239 | -------------------------------------------------------------------------------- /runtime/functionObject.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/16. 3 | // 4 | 5 | #ifndef PYTHONVM_FUNCTIONOBJECT_HPP 6 | #define PYTHONVM_FUNCTIONOBJECT_HPP 7 | 8 | #include "util/map.hpp" 9 | #include "code/codeObject.hpp" 10 | #include "object/klass.hpp" 11 | 12 | class FunctionKlass : public Klass { 13 | private: 14 | FunctionKlass(); 15 | 16 | static FunctionKlass *instance; 17 | 18 | public: 19 | static FunctionKlass *get_instance(); 20 | 21 | virtual void print(HiObject *obj); 22 | 23 | virtual size_t size(); 24 | virtual void oops_do(OopClosure *f, HiObject *obj); 25 | }; 26 | 27 | typedef HiObject *(*NativeFuncPointer)(ObjList args); 28 | 29 | class FunctionObject : public HiObject { 30 | friend class FunctionKlass; 31 | friend class NativeFunctionKlass; 32 | friend class FrameObject; 33 | 34 | private: 35 | CodeObject *_func_code; 36 | HiString *_func_name; 37 | HiDict *_globals; 38 | HiList* _closure; 39 | ObjList _defaults; 40 | 41 | NativeFuncPointer _native_func; 42 | 43 | unsigned int _flags; 44 | 45 | public: 46 | enum CO_FLAGS { 47 | CO_VARARGS = 0x4, 48 | CO_VARKEYWORDS = 0x8, 49 | CO_GENERATOR = 0x20, 50 | }; 51 | 52 | FunctionObject(HiObject *code_object); 53 | 54 | FunctionObject(NativeFuncPointer nfp); 55 | 56 | FunctionObject(Klass *klass) { 57 | _func_code = NULL; 58 | _func_name = NULL; 59 | _globals = NULL; 60 | _defaults = NULL; 61 | _flags = 0; 62 | 63 | set_klass(klass); 64 | } 65 | 66 | HiString *func_name() { return _func_name; } 67 | int flags() { return _flags; } 68 | 69 | HiDict *globals() { return _globals; } 70 | void set_globals(HiDict *x) { _globals = x; } 71 | 72 | void set_closure(HiList *x) { _closure = x; } 73 | HiList *closure() { return _closure; } 74 | 75 | void set_default(ObjList defaults); 76 | ObjList defaults() { return _defaults; } 77 | 78 | HiObject *call(ObjList args); 79 | }; 80 | 81 | class NativeFunctionKlass : public Klass { 82 | private: 83 | NativeFunctionKlass(); 84 | 85 | static NativeFunctionKlass *instance; 86 | 87 | public: 88 | static NativeFunctionKlass *get_instance(); 89 | virtual size_t size(); 90 | virtual void oops_do(OopClosure *f, HiObject *obj); 91 | }; 92 | 93 | class MethodKlass : public Klass { 94 | private: 95 | MethodKlass(); 96 | static MethodKlass* instance; 97 | 98 | public: 99 | static MethodKlass* get_instance(); 100 | virtual size_t size(); 101 | virtual void oops_do(OopClosure *f, HiObject *obj); 102 | }; 103 | 104 | class MethodObject : public HiObject { 105 | friend class MethodKlass; 106 | 107 | private: 108 | HiObject* _owner; 109 | FunctionObject *_func; 110 | 111 | public: 112 | MethodObject(FunctionObject *func) : _owner(NULL), _func(func) { 113 | set_klass(MethodKlass::get_instance()); 114 | } 115 | 116 | MethodObject(FunctionObject *func, HiObject *owner) : _owner(owner), _func(func) { 117 | set_klass(MethodKlass::get_instance()); 118 | } 119 | 120 | void set_owner(HiObject *x) { _owner = x; } 121 | HiObject *owner() { return _owner; } 122 | FunctionObject *func() { return _func; } 123 | 124 | static bool is_function(HiObject *x); 125 | static bool is_yield_function(HiObject *x); 126 | }; 127 | 128 | HiObject* len(ObjList args); 129 | HiObject* iter(ObjList args); 130 | HiObject* isinstance(ObjList args); 131 | HiObject* type_of(ObjList args); 132 | 133 | #endif //PYTHONVM_FUNCTIONOBJECT_HPP 134 | -------------------------------------------------------------------------------- /runtime/generator.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/10/13. 3 | // 4 | 5 | #include "runtime/generator.hpp" 6 | #include "runtime/functionObject.hpp" 7 | #include "runtime/frameObject.hpp" 8 | #include "runtime/interpreter.hpp" 9 | #include "code/codeObject.hpp" 10 | #include "object/hiDict.hpp" 11 | #include "object/hiList.hpp" 12 | #include "object/hiString.hpp" 13 | #include "memory/oopClosure.hpp" 14 | 15 | GeneratorKlass *GeneratorKlass::instance = NULL; 16 | 17 | GeneratorKlass::GeneratorKlass() { 18 | HiDict *klass_dict = new HiDict(); 19 | klass_dict->put(new HiString("next"), new FunctionObject(generator_next)); 20 | set_klass_dict(klass_dict); 21 | } 22 | 23 | GeneratorKlass *GeneratorKlass::get_instance() { 24 | if (instance == NULL) 25 | instance = new GeneratorKlass(); 26 | 27 | return instance; 28 | } 29 | 30 | HiObject *GeneratorKlass::iter(HiObject *obj) { 31 | return obj; 32 | } 33 | 34 | HiObject *GeneratorKlass::next(HiObject *obj) { 35 | assert(obj->klass() == (Klass *) this); 36 | Generator *g = (Generator *) obj; 37 | return Interpreter::get_instance()->eval_generator(g); 38 | } 39 | 40 | size_t GeneratorKlass::size() { 41 | return sizeof(Generator); 42 | } 43 | 44 | void GeneratorKlass::oops_do(OopClosure *f, HiObject *obj) { 45 | Generator *g = (Generator *) obj; 46 | assert(g->klass() == (Klass *) this); 47 | 48 | if (g->frame()) 49 | g->frame()->oops_do(f); 50 | } 51 | 52 | Generator::Generator(FunctionObject *func, ArrayList *args, int arg_cnt) { 53 | _frame = new FrameObject(func, args, arg_cnt); 54 | set_klass(GeneratorKlass::get_instance()); 55 | } 56 | 57 | HiObject *generator_next(ObjList args) { 58 | Generator *generator = (Generator *) (args->get(0)); 59 | return generator->next(); 60 | } 61 | -------------------------------------------------------------------------------- /runtime/generator.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/10/13. 3 | // 4 | 5 | #ifndef PYTHONVM_GENERATOR_HPP 6 | #define PYTHONVM_GENERATOR_HPP 7 | 8 | #include "object/hiObject.hpp" 9 | #include "object/klass.hpp" 10 | #include "util/arrayList.hpp" 11 | #include "util/stack.hpp" 12 | 13 | class OopClosure; 14 | class FunctionObject; 15 | class CodeObject; 16 | class HiDict; 17 | class HiList; 18 | class FrameObject; 19 | class Interpreter; 20 | class Block; 21 | 22 | class GeneratorKlass : public Klass { 23 | private: 24 | static GeneratorKlass *instance; 25 | 26 | GeneratorKlass(); 27 | 28 | public: 29 | static GeneratorKlass *get_instance(); 30 | 31 | virtual HiObject *next(HiObject *obj); 32 | 33 | virtual HiObject *iter(HiObject *obj); 34 | 35 | virtual size_t size(); 36 | 37 | virtual void oops_do(OopClosure *f, HiObject *obj); 38 | }; 39 | 40 | class Generator : public HiObject { 41 | friend class Interpreter; 42 | friend class FrameObject; 43 | friend class GeneratorKlass; 44 | 45 | private: 46 | FrameObject *_frame; 47 | 48 | public: 49 | Generator(FunctionObject *func, ArrayList *args, int arg_cnt); 50 | 51 | FrameObject *frame() { 52 | return _frame; 53 | } 54 | 55 | void set_frame(FrameObject *x) { 56 | _frame = x; 57 | } 58 | }; 59 | 60 | HiObject* generator_next(ObjList args); 61 | 62 | #endif //PYTHONVM_GENERATOR_HPP 63 | -------------------------------------------------------------------------------- /runtime/interpreter.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/15. 3 | // 4 | 5 | #include "code/bytecode.hpp" 6 | #include "runtime/interpreter.hpp" 7 | #include "runtime/frameObject.hpp" 8 | #include "runtime/universe.hpp" 9 | #include "runtime/functionObject.hpp" 10 | #include "runtime/stringTable.hpp" 11 | #include "runtime/cellObject.hpp" 12 | #include "runtime/module.hpp" 13 | #include "runtime/generator.hpp" 14 | #include "object/hiString.hpp" 15 | #include "object/hiInteger.hpp" 16 | #include "object/hiList.hpp" 17 | #include "object/hiDict.hpp" 18 | #include "traceback.hpp" 19 | #include "memory/oopClosure.hpp" 20 | #include "util/map.hpp" 21 | #include "util/handles.hpp" 22 | 23 | #define PUSH(x) _frame->stack()->append(x) 24 | #define POP() _frame->stack()->pop() 25 | #define TOP() _frame->stack()->top() 26 | #define STACK_LEVEL() _frame->stack()->size() 27 | #define PEEK(x) _frame->stack()->get((x)) 28 | 29 | #define HI_TRUE Universe::HiTrue 30 | #define HI_FALSE Universe::HiFalse 31 | 32 | #define ST(x) StringTable::get_instance()->STR(x) 33 | #define STR(x) x##_str 34 | 35 | Interpreter *Interpreter::_instance = NULL; 36 | 37 | Interpreter *Interpreter::get_instance() { 38 | if (_instance == NULL) { 39 | _instance = new Interpreter(); 40 | } 41 | 42 | return _instance; 43 | } 44 | 45 | Interpreter::Interpreter() { 46 | _frame = NULL; 47 | 48 | _int_status = IS_OK; 49 | 50 | // prepare for import builtin, this should be created first 51 | _builtins = new ModuleObject(new HiDict()); 52 | _builtins->put(new HiString("True"), Universe::HiTrue); 53 | _builtins->put(new HiString("False"), Universe::HiFalse); 54 | _builtins->put(new HiString("None"), Universe::HiNone); 55 | 56 | _builtins->put(new HiString("len"), new FunctionObject(len)); 57 | _builtins->put(new HiString("iter"), new FunctionObject(iter)); 58 | _builtins->put(new HiString("type"), new FunctionObject(type_of)); 59 | _builtins->put(new HiString("isinstance"), new FunctionObject(isinstance)); 60 | 61 | _builtins->put(new HiString("int"), IntegerKlass::get_instance()->type_object()); 62 | _builtins->put(new HiString("object"), ObjectKlass::get_instance()->type_object()); 63 | _builtins->put(new HiString("str"), StringKlass::get_instance()->type_object()); 64 | _builtins->put(new HiString("list"), ListKlass::get_instance()->type_object()); 65 | _builtins->put(new HiString("dict"), DictKlass::get_instance()->type_object()); 66 | } 67 | 68 | void Interpreter::initialize() { 69 | _builtins->extend(ModuleObject::import_module((HiString *) Universe::HiNone, new HiString("builtin"))); 70 | Universe::stop_iteration = _builtins->get(new HiString("StopIteration")); 71 | 72 | _modules = new HiDict(); 73 | _modules->put(new HiString("__builtins__"), _builtins); 74 | } 75 | 76 | void Interpreter::run(CodeObject *codes) { 77 | _frame = new FrameObject(codes); 78 | _frame->locals()->put(ST(name), new HiString("__main__")); 79 | 80 | eval_frame(); 81 | 82 | if (_int_status == IS_EXCEPTION) { 83 | _int_status = IS_OK; 84 | 85 | _trace_back->print(); 86 | _pending_exception->print(); 87 | printf("\n"); 88 | 89 | _trace_back = NULL; 90 | _pending_exception = NULL; 91 | _exception_class = NULL; 92 | } 93 | 94 | destroy_frame(); 95 | } 96 | 97 | HiDict *Interpreter::run_mod(CodeObject *codes, HiString *mod_name) { 98 | FrameObject *frame = new FrameObject(codes); 99 | frame->set_entry_frame(true); 100 | frame->locals()->put(ST(name), mod_name); 101 | 102 | enter_frame(frame); 103 | eval_frame(); 104 | HiDict *result = frame->locals(); 105 | destroy_frame(); 106 | return result; 107 | } 108 | 109 | void Interpreter::eval_frame() { 110 | Block *b; 111 | FunctionObject *fo; 112 | ArrayList *args = NULL; 113 | 114 | HiObject *lhs, *rhs; 115 | HiObject *v, *w, *u, *attr; 116 | HiList *stack; 117 | 118 | unsigned char op_code; 119 | bool has_arg; 120 | int op_arg; 121 | 122 | while (_frame->has_more_codes()) { 123 | op_code = _frame->get_op_code(); 124 | bool has_arg = (op_code & 0xFF) >= ByteCode::HAVE_ARGUMENT; 125 | 126 | int op_arg = -1; 127 | if (has_arg) { 128 | op_arg = _frame->get_op_arg(); 129 | } 130 | 131 | switch (op_code) { 132 | case ByteCode::POP_TOP: 133 | POP(); 134 | break; 135 | 136 | case ByteCode::ROT_TWO: 137 | v = POP(); 138 | w = POP(); 139 | PUSH(v); 140 | PUSH(w); 141 | break; 142 | 143 | case ByteCode::ROT_THREE: 144 | v = POP(); 145 | w = POP(); 146 | u = POP(); 147 | PUSH(v); 148 | PUSH(u); 149 | PUSH(w); 150 | break; 151 | 152 | case ByteCode::BINARY_MULTIPLY: 153 | case ByteCode::INPLACE_MULTIPLY: 154 | v = POP(); 155 | w = POP(); 156 | PUSH(w->mul(v)); 157 | break; 158 | 159 | case ByteCode::DUP_TOP: 160 | PUSH(TOP()); 161 | break; 162 | 163 | case ByteCode::BINARY_DIVIDE: 164 | case ByteCode::INPLACE_DIVIDE: 165 | v = POP(); 166 | w = POP(); 167 | PUSH(w->div(v)); 168 | break; 169 | 170 | case ByteCode::BINARY_MODULO: 171 | case ByteCode::INPLACE_MODULO: 172 | v = POP(); 173 | w = POP(); 174 | // TODO 175 | // PUSH(w->mod(v)); 176 | u = w->mod(v); 177 | stack = _frame->stack(); 178 | stack->append(u); 179 | break; 180 | 181 | case ByteCode::BINARY_ADD: 182 | case ByteCode::INPLACE_ADD: 183 | v = POP(); 184 | w = POP(); 185 | // PUSH(w->add(v)); 186 | // _frame->stack()->append(w->add(v)); 187 | stack = _frame->stack(); 188 | u = w->add(v); 189 | stack->append(u); 190 | break; 191 | 192 | case ByteCode::BINARY_SUBTRACT: 193 | case ByteCode::INPLACE_SUBSTRACT: 194 | v = POP(); 195 | w = POP(); 196 | PUSH(w->sub(v)); 197 | break; 198 | 199 | case ByteCode::BINARY_SUBSCR: 200 | v = POP(); 201 | w = POP(); 202 | PUSH(w->subscr(v)); 203 | break; 204 | 205 | case ByteCode::STORE_MAP: 206 | w = POP(); 207 | u = POP(); 208 | v = TOP(); 209 | ((HiDict *) v)->put(w, u); 210 | break; 211 | 212 | case ByteCode::STORE_SUBSCR: 213 | u = POP(); 214 | v = POP(); 215 | w = POP(); 216 | v->store_subscr(u, w); 217 | break; 218 | 219 | case ByteCode::DELETE_SUBSCR: 220 | v = POP(); 221 | w = POP(); 222 | w->del_subscr(v); 223 | break; 224 | 225 | case ByteCode::GET_ITER: 226 | v = POP(); 227 | PUSH(v->iter()); 228 | break; 229 | 230 | case ByteCode::FOR_ITER: 231 | v = TOP(); 232 | w = v->next(); 233 | 234 | if (w == NULL) { 235 | // we may encounter a StopIteration, ignore it. 236 | // assert(_int_status == IS_EXCEPTION && _pending_exception != NULL); 237 | _frame->_pc += op_arg; 238 | _int_status = IS_OK; 239 | _pending_exception = NULL; 240 | } else { 241 | PUSH(w); 242 | } 243 | break; 244 | 245 | case ByteCode::PRINT_ITEM: 246 | v = POP(); 247 | v->print(); 248 | break; 249 | 250 | case ByteCode::PRINT_NEWLINE: 251 | printf("\n"); 252 | break; 253 | 254 | case ByteCode::BREAK_LOOP: 255 | _int_status = IS_BREAK; 256 | break; 257 | 258 | case ByteCode::LOAD_LOCALS: 259 | PUSH(_frame->locals()); 260 | break; 261 | 262 | case ByteCode::YIELD_VALUE: 263 | // we are assured that we're in the progress of evalating generator. 264 | _int_status = IS_YIELD; 265 | _ret_value = TOP(); 266 | return; 267 | 268 | case ByteCode::POP_BLOCK: 269 | b = _frame->_loop_stack->pop(); 270 | while (STACK_LEVEL() > b->_level) { 271 | POP(); 272 | } 273 | break; 274 | 275 | case ByteCode::END_FINALLY: 276 | // restore state before finally 277 | v = POP(); 278 | if (((long) v) & 0x1) { 279 | _int_status = (Status) (((long) v) >> 1); 280 | if (_int_status == IS_RETURN) { 281 | _ret_value = POP(); 282 | } else if (_int_status == IS_CONTINUE) { 283 | _frame->_pc = (int) ((long) POP()); 284 | } 285 | } else if (v != Universe::HiNone) { 286 | _exception_class = v; 287 | _pending_exception = POP(); 288 | _trace_back = POP(); 289 | _int_status = IS_EXCEPTION; 290 | } 291 | break; 292 | 293 | case ByteCode::BUILD_CLASS: 294 | // locals 295 | v = POP(); 296 | // supers 297 | u = POP(); 298 | // name 299 | w = POP(); 300 | v = Klass::create_klass(v, u, w); 301 | PUSH(v); 302 | break; 303 | 304 | case ByteCode::STORE_NAME: 305 | v = _frame->names()->get(op_arg); 306 | _frame->locals()->put(v, POP()); 307 | break; 308 | 309 | case ByteCode::UNPACK_SEQUENCE: 310 | v = POP(); 311 | while (op_arg--) { 312 | PUSH(v->subscr(new HiInteger(op_arg))); 313 | } 314 | break; 315 | 316 | case ByteCode::STORE_ATTR: 317 | u = POP(); 318 | v = _frame->names()->get(op_arg); 319 | w = POP(); 320 | u->setattr(v, w); 321 | break; 322 | 323 | case ByteCode::STORE_GLOBAL: 324 | v = _frame->names()->get(op_arg); 325 | _frame->globals()->put(v, POP()); 326 | break; 327 | 328 | case ByteCode::DUP_TOPX: 329 | for (int i = 0; i < op_arg; i++) { 330 | int index = STACK_LEVEL() - op_arg; 331 | PUSH(PEEK(index)); 332 | } 333 | break; 334 | 335 | case ByteCode::LOAD_CONST: 336 | v = _frame->consts()->get(op_arg); 337 | PUSH(v); 338 | break; 339 | 340 | case ByteCode::LOAD_NAME: 341 | v = _frame->names()->get(op_arg); 342 | w = _frame->locals()->get(v); 343 | if (w != Universe::HiNone) { 344 | PUSH(w); 345 | break; 346 | } 347 | 348 | w = _frame->globals()->get(v); 349 | if (w != Universe::HiNone) { 350 | PUSH(w); 351 | break; 352 | } 353 | 354 | w = _builtins->get(v); 355 | if (w != Universe::HiNone) { 356 | PUSH(w); 357 | break; 358 | } 359 | 360 | PUSH(Universe::HiNone); 361 | break; 362 | 363 | case ByteCode::BUILD_TUPLE: 364 | case ByteCode::BUILD_LIST: 365 | v = new HiList(); 366 | while (op_arg--) { 367 | ((HiList *) v)->set(op_arg, POP()); 368 | } 369 | 370 | PUSH(v); 371 | break; 372 | 373 | case ByteCode::BUILD_MAP: 374 | v = new HiDict(); 375 | PUSH(v); 376 | break; 377 | 378 | case ByteCode::LOAD_ATTR: 379 | v = POP(); 380 | w = _frame->_names->get(op_arg); 381 | PUSH(v->getattr(w)); 382 | break; 383 | 384 | case ByteCode::COMPARE_OP: 385 | w = POP(); 386 | v = POP(); 387 | 388 | switch (op_arg) { 389 | case ByteCode::GREATER: 390 | PUSH(v->greater(w)); 391 | break; 392 | case ByteCode::LESS: 393 | PUSH(v->less(w)); 394 | break; 395 | 396 | case ByteCode::EQUAL: 397 | PUSH(v->equal(w)); 398 | break; 399 | 400 | case ByteCode::NOT_EQUAL: 401 | PUSH(v->not_equal(w)); 402 | break; 403 | 404 | case ByteCode::GREATER_EQUAL: 405 | PUSH(v->ge(w)); 406 | break; 407 | 408 | case ByteCode::IN: 409 | PUSH(w->contains(v)); 410 | break; 411 | 412 | case ByteCode::LESS_EQUAL: 413 | PUSH(v->le(w)); 414 | break; 415 | 416 | case ByteCode::IS: 417 | if (v == w) { 418 | PUSH(HI_TRUE); 419 | } else { 420 | PUSH(HI_FALSE); 421 | } 422 | break; 423 | 424 | case ByteCode::IS_NOT: 425 | if (v == w) { 426 | PUSH(HI_FALSE); 427 | } else { 428 | PUSH(HI_TRUE); 429 | } 430 | break; 431 | 432 | case ByteCode::EXC_MATCH: { 433 | bool found = false; 434 | Klass *k = ((HiTypeObject *) v)->own_klass(); 435 | if (v == w) { 436 | found = true; 437 | } else { 438 | for (int i = 0; i < k->mro()->size(); i++) { 439 | if (v->klass()->mro()->get(i) == w) { 440 | found = true; 441 | break; 442 | } 443 | } 444 | } 445 | 446 | if (found) { 447 | PUSH(Universe::HiTrue); 448 | } else { 449 | PUSH(Universe::HiFalse); 450 | } 451 | 452 | break; 453 | } 454 | 455 | default: 456 | printf("Error: Unrecognized compare op %d\n", op_arg); 457 | } 458 | break; 459 | 460 | case ByteCode::IMPORT_NAME: 461 | POP(); 462 | POP(); 463 | v = _frame->names()->get(op_arg); 464 | w = _modules->get(v); 465 | if (w != Universe::HiNone) { 466 | PUSH(w); 467 | break; 468 | } 469 | 470 | HiString *cur_code_path; 471 | if (_frame->_codes->_file_path != NULL) { 472 | cur_code_path = _frame->_codes->_file_path; 473 | } else { 474 | cur_code_path = Universe::main_code->_file_path; 475 | } 476 | 477 | w = ModuleObject::import_module(cur_code_path, v); 478 | _modules->put(v, w); 479 | PUSH(w); 480 | break; 481 | 482 | case ByteCode::IMPORT_FROM: 483 | v = _frame->names()->get(op_arg); 484 | w = TOP(); 485 | u = ((ModuleObject *) w)->get(v); 486 | PUSH(u); 487 | break; 488 | 489 | case ByteCode::POP_JUMP_IF_FALSE: 490 | v = POP(); 491 | if (v == Universe::HiFalse) { 492 | _frame->set_pc(op_arg); 493 | } 494 | break; 495 | 496 | case ByteCode::POP_JUMP_IF_TRUE: 497 | v = POP(); 498 | if (v == Universe::HiTrue) { 499 | _frame->set_pc(op_arg); 500 | } 501 | break; 502 | 503 | case ByteCode::JUMP_FORWARD: 504 | _frame->set_pc(op_arg + _frame->get_pc()); 505 | break; 506 | 507 | case ByteCode::JUMP_ABSOLUTE: 508 | _frame->set_pc(op_arg); 509 | break; 510 | 511 | case ByteCode::LOAD_GLOBAL: 512 | v = _frame->names()->get(op_arg); 513 | w = _frame->globals()->get(v); 514 | if (w != Universe::HiNone) { 515 | PUSH(w); 516 | break; 517 | } 518 | 519 | w = _builtins->get(v); 520 | if (w != Universe::HiNone) { 521 | PUSH(w); 522 | break; 523 | } 524 | 525 | PUSH(Universe::HiNone); 526 | break; 527 | 528 | case ByteCode::CONTINUE_LOOP: 529 | _int_status = IS_CONTINUE; 530 | _ret_value = (HiObject *) ((long) op_arg); 531 | break; 532 | 533 | case ByteCode::SETUP_LOOP: 534 | case ByteCode::SETUP_EXCEPT: 535 | case ByteCode::SETUP_FINALLY: 536 | _frame->loop_stack()->add(new Block( 537 | op_code, _frame->get_pc() + op_arg, 538 | STACK_LEVEL())); 539 | break; 540 | 541 | case ByteCode::LOAD_FAST: 542 | PUSH(_frame->fast_locals()->get(op_arg)); 543 | break; 544 | 545 | case ByteCode::STORE_FAST: 546 | _frame->fast_locals()->set(op_arg, POP()); 547 | break; 548 | 549 | case ByteCode::RAISE_VARARGS: 550 | w = v = u = NULL; 551 | switch (op_arg) { 552 | case 3: 553 | u = POP(); 554 | case 2: 555 | v = POP(); 556 | case 1: 557 | w = POP(); 558 | break; 559 | } 560 | 561 | do_raise(w, v, u); 562 | break; 563 | 564 | case ByteCode::CALL_FUNCTION: 565 | if (op_arg > 0) { 566 | int arg_num = op_arg & 0xff; 567 | int key_arg_num = op_arg >> 8; 568 | int arg_cnt = arg_num + 2 * key_arg_num; 569 | args = new ArrayList(arg_cnt); 570 | while (arg_cnt--) { 571 | args->set(arg_cnt, POP()); 572 | } 573 | } 574 | build_frame(POP(), args, op_arg); 575 | 576 | if (args != NULL) { 577 | args = NULL; 578 | } 579 | break; 580 | 581 | case ByteCode::MAKE_FUNCTION: 582 | v = POP(); 583 | fo = new FunctionObject(v); 584 | fo->set_globals(_frame->globals()); 585 | if (op_arg > 0) { 586 | args = new ArrayList(op_arg); 587 | while (op_arg--) { 588 | args->set(op_arg, POP()); 589 | } 590 | } 591 | 592 | fo->set_default(args); 593 | 594 | if (args != NULL) { 595 | args = NULL; 596 | } 597 | 598 | PUSH(fo); 599 | break; 600 | 601 | case ByteCode::MAKE_CLOSURE: 602 | v = POP(); 603 | fo = new FunctionObject(v); 604 | fo->set_closure((HiList *) POP()); 605 | fo->set_globals(_frame->globals()); 606 | if (op_arg > 0) { 607 | args = new ArrayList(op_arg); 608 | while (op_arg--) { 609 | args->set(op_arg, POP()); 610 | } 611 | } 612 | fo->set_default(args); 613 | 614 | if (args != NULL) { 615 | args = NULL; 616 | } 617 | 618 | PUSH(fo); 619 | break; 620 | 621 | case ByteCode::LOAD_CLOSURE: 622 | v = _frame->closure()->get(op_arg); 623 | // 为空说明不是局部变量而是参数 624 | if (v == NULL) { 625 | v = _frame->get_cell_from_parameter(op_arg); 626 | _frame->closure()->set(op_arg, v); 627 | } 628 | 629 | if (v->klass() == CellKlass::get_instance()) { 630 | PUSH(v); 631 | } else { 632 | PUSH(new CellObject(_frame->closure(), op_arg)); 633 | } 634 | break; 635 | 636 | case ByteCode::LOAD_DEREF: 637 | v = _frame->closure()->get(op_arg); 638 | if (v->klass() == CellKlass::get_instance()) { 639 | v = ((CellObject *) v)->value(); 640 | } 641 | PUSH(v); 642 | break; 643 | 644 | case ByteCode::STORE_DEREF: 645 | _frame->closure()->set(op_arg, POP()); 646 | break; 647 | 648 | case ByteCode::CALL_FUNCTION_VAR: 649 | v = POP(); 650 | if (op_arg > 0 || (v && ((HiList *) v)->size() > 0)) { 651 | int arg_num = op_arg & 0xff; 652 | int key_arg_num = op_arg >> 8; 653 | int arg_cnt = arg_num + 2 * key_arg_num; 654 | args = new ArrayList(); 655 | while (arg_cnt--) { 656 | args->set(arg_cnt, POP()); 657 | } 658 | 659 | int s = ((HiList *) v)->size(); 660 | for (int i = 0; i < s; i++) { 661 | args->add(((HiList *) v)->get(i)); 662 | } 663 | arg_num += s; 664 | op_arg = (key_arg_num << 8) | arg_num; 665 | } 666 | 667 | build_frame(POP(), args, op_arg); 668 | 669 | if (args != NULL) { 670 | args = NULL; 671 | } 672 | break; 673 | 674 | case ByteCode::RETURN_VALUE: 675 | _ret_value = POP(); 676 | _int_status = IS_RETURN; 677 | break; 678 | 679 | default: 680 | printf("Error: Unrecognized byte code %d\n", op_code); 681 | } 682 | 683 | while (_int_status != IS_OK && _frame->loop_stack()->size() != 0) { 684 | b = _frame->_loop_stack->get(_frame->_loop_stack->size() - 1); 685 | if (_int_status == IS_CONTINUE && b->_type == ByteCode::SETUP_LOOP) { 686 | _frame->_pc = (int) ((long long) _ret_value); 687 | _int_status = IS_OK; 688 | break; 689 | } 690 | 691 | b = _frame->_loop_stack->pop(); 692 | while (STACK_LEVEL() > b->_level) { 693 | POP(); 694 | } 695 | 696 | if (_int_status == IS_BREAK && b->_type == ByteCode::SETUP_LOOP) { 697 | _frame->_pc = b->_target; 698 | _int_status = IS_OK; 699 | } else if (b->_type == ByteCode::SETUP_FINALLY || 700 | (_int_status == IS_EXCEPTION 701 | && b->_type == ByteCode::SETUP_EXCEPT)) { 702 | if (_int_status == IS_EXCEPTION) { 703 | // traceback, value, exception class 704 | PUSH(_trace_back); 705 | PUSH(_pending_exception); 706 | PUSH(_exception_class); 707 | 708 | _trace_back = NULL; 709 | _pending_exception = NULL; 710 | _exception_class = NULL; 711 | } else { 712 | if (_int_status == IS_RETURN || _int_status == IS_CONTINUE) { 713 | PUSH(_ret_value); 714 | } 715 | 716 | // 用倒数第一位标记一下是直接整数而不是指针 717 | PUSH((HiObject *) (((long) _int_status << 1) | 0x1)); 718 | } 719 | 720 | _frame->_pc = b->_target; 721 | _int_status = IS_OK; 722 | } 723 | } 724 | 725 | // has pending exception and no handler found, unwind stack. 726 | if (_int_status != IS_OK && _frame->_loop_stack->size() == 0) { 727 | if (_int_status == IS_EXCEPTION) { 728 | _ret_value = NULL; 729 | ((Traceback *) _trace_back)->record_frame(_frame); 730 | } 731 | 732 | if (_int_status == IS_RETURN) { 733 | _int_status = IS_OK; 734 | } 735 | 736 | if (_frame->is_first_frame() || 737 | _frame->is_entry_frame()) { 738 | return; 739 | } 740 | 741 | leave_frame(); 742 | } 743 | } 744 | } 745 | 746 | HiObject *Interpreter::eval_generator(Generator *g) { 747 | if (g->frame() == NULL) { 748 | // 说明frame已经被销毁了 749 | do_raise(Universe::stop_iteration, NULL, NULL); 750 | return NULL; 751 | } 752 | 753 | Handle handle(g); 754 | enter_frame(g->frame()); 755 | g->_frame->set_entry_frame(true); 756 | eval_frame(); 757 | 758 | if (_int_status != IS_YIELD) { 759 | _int_status = IS_OK; 760 | leave_frame(); 761 | ((Generator *) handle())->set_frame(NULL); 762 | return NULL; 763 | } 764 | 765 | _int_status = IS_OK; 766 | _frame = _frame->sender(); 767 | 768 | return _ret_value; 769 | } 770 | 771 | void Interpreter::destroy_frame() { 772 | FrameObject *temp = _frame; 773 | _frame = _frame->sender(); 774 | delete temp; 775 | } 776 | 777 | void Interpreter::build_frame(HiObject *callable, ObjList args, int op_arg) { 778 | if (callable->klass() == NativeFunctionKlass::get_instance()) { 779 | PUSH(((FunctionObject *) callable)->call(args)); 780 | } else if (callable->klass() == MethodKlass::get_instance()) { 781 | MethodObject *method = (MethodObject *) callable; 782 | if (!args) { 783 | args = new ArrayList(1); 784 | } 785 | args->insert(0, method->owner()); 786 | build_frame(method->func(), args, op_arg + 1); 787 | } else if (MethodObject::is_yield_function(callable)) { 788 | Generator *generator = new Generator((FunctionObject *) callable, args, op_arg); 789 | PUSH(generator); 790 | return; 791 | } else if (callable->klass() == FunctionKlass::get_instance()) { 792 | FrameObject *frame = new FrameObject((FunctionObject *) callable, args, op_arg); 793 | frame->set_sender(_frame); 794 | _frame = frame; 795 | } else if (callable->klass() == TypeKlass::get_instance()) { 796 | HiObject *instance = ((HiTypeObject *) callable)->own_klass()-> 797 | allocate_instance(callable, args); 798 | PUSH(instance); 799 | } else { 800 | // __call__ 801 | HiObject *m = callable->getattr(ST(call)); 802 | if (m != Universe::HiNone) { 803 | build_frame(m, args, op_arg); 804 | } else { 805 | callable->print(); 806 | printf("\nError : can not call a normal object.\n"); 807 | } 808 | } 809 | } 810 | 811 | void Interpreter::leave_frame() { 812 | destroy_frame(); 813 | PUSH(_ret_value); 814 | } 815 | 816 | HiObject *Interpreter::call_virtual(HiObject *func, ObjList args) { 817 | if (func->klass() == NativeFunctionKlass::get_instance()) { 818 | // we do not create a virtual frame, but native frame. 819 | return ((FunctionObject *) func)->call(args); 820 | } else if (func->klass() == MethodKlass::get_instance()) { 821 | MethodObject *method = (MethodObject *) func; 822 | if (!args) { 823 | args = new ArrayList(1); 824 | } 825 | args->insert(0, method->owner()); 826 | return call_virtual(method->func(), args); 827 | } else if (MethodObject::is_function(func)) { 828 | int size = args ? args->size() : 0; 829 | FrameObject *frame = new FrameObject((FunctionObject *) func, args, size); 830 | frame->set_entry_frame(true); 831 | enter_frame(frame); 832 | eval_frame(); 833 | destroy_frame(); 834 | return _ret_value; 835 | } 836 | 837 | return Universe::HiNone; 838 | } 839 | 840 | void Interpreter::enter_frame(FrameObject *frame) { 841 | frame->set_sender(_frame); 842 | _frame = frame; 843 | } 844 | 845 | void Interpreter::oops_do(OopClosure *f) { 846 | f->do_oop((HiObject **) &_builtins); 847 | f->do_oop((HiObject **) &_modules); 848 | f->do_oop((HiObject **) &_ret_value); 849 | 850 | if (_frame) { 851 | _frame->oops_do(f); 852 | } 853 | } 854 | 855 | Interpreter::Status Interpreter::do_raise(HiObject *exc, HiObject *val, HiObject *tb) { 856 | assert(exc != NULL); 857 | 858 | _int_status = IS_EXCEPTION; 859 | 860 | if (tb == NULL) { 861 | tb = new Traceback(); 862 | } 863 | 864 | if (val != NULL) { 865 | _exception_class = exc; 866 | _pending_exception = val; 867 | _trace_back = tb; 868 | return IS_EXCEPTION; 869 | } 870 | 871 | if (exc->klass() == TypeKlass::get_instance()) { 872 | _pending_exception = call_virtual(exc, NULL); 873 | _exception_class = exc; 874 | } else { 875 | _pending_exception = exc; 876 | _exception_class = _pending_exception->klass()->type_object(); 877 | } 878 | 879 | _trace_back = tb; 880 | return IS_EXCEPTION; 881 | } -------------------------------------------------------------------------------- /runtime/interpreter.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/15. 3 | // 4 | 5 | #ifndef PYTHONVM_INTERPRETER_HPP 6 | #define PYTHONVM_INTERPRETER_HPP 7 | 8 | #include "code/bytecode.hpp" 9 | #include "code/codeObject.hpp" 10 | #include "module.hpp" 11 | 12 | class FrameObject; 13 | 14 | class HiDict; 15 | 16 | class OopClosure; 17 | 18 | class Generator; 19 | 20 | class Interpreter { 21 | enum Status { 22 | IS_OK, 23 | IS_BREAK, 24 | IS_CONTINUE, 25 | IS_EXCEPTION, 26 | IS_RETURN, 27 | IS_YIELD 28 | }; 29 | 30 | private: 31 | ModuleObject *_builtins; 32 | HiDict *_modules; 33 | FrameObject *_frame; 34 | HiObject *_ret_value; 35 | 36 | HiObject *_exception_class; 37 | HiObject *_pending_exception; 38 | HiObject *_trace_back; 39 | Status _int_status; 40 | 41 | static Interpreter *_instance; 42 | 43 | Interpreter(); 44 | 45 | public: 46 | static Interpreter *get_instance(); 47 | 48 | void initialize(); 49 | 50 | void run(CodeObject *codes); 51 | 52 | HiDict *run_mod(CodeObject *codes, HiString *mod_name); 53 | 54 | void build_frame(HiObject *pObject, ObjList args, int op_arg); 55 | 56 | void enter_frame(FrameObject *frame); 57 | 58 | void eval_frame(); 59 | 60 | void destroy_frame(); 61 | 62 | void leave_frame(); 63 | 64 | HiObject *call_virtual(HiObject *func, ObjList args); 65 | 66 | HiObject *eval_generator(Generator *g); 67 | 68 | /** 69 | * 抛出异常 70 | * 71 | * @param exc 异常类型 72 | * @param val 异常实例 73 | * @param tb 异常堆栈 74 | * @return 状态 75 | */ 76 | Status do_raise(HiObject *exc, HiObject *val, HiObject *tb); 77 | 78 | void oops_do(OopClosure *f); 79 | }; 80 | 81 | #endif //PYTHONVM_INTERPRETER_HPP 82 | -------------------------------------------------------------------------------- /runtime/module.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/9/26. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "inc/koshox.hpp" 10 | #include "object/hiDict.hpp" 11 | #include "object/hiList.hpp" 12 | #include "runtime/module.hpp" 13 | #include "runtime/universe.hpp" 14 | #include "runtime/interpreter.hpp" 15 | #include "runtime/stringTable.hpp" 16 | #include "util/bufferedInputStream.hpp" 17 | #include "code/binaryFileParser.hpp" 18 | #include "memory/oopClosure.hpp" 19 | 20 | #define ST(x) StringTable::get_instance()->STR(x) 21 | #define STR(x) x##_str 22 | 23 | ModuleKlass *ModuleKlass::_instance = NULL; 24 | 25 | ModuleKlass *ModuleKlass::get_instance() { 26 | if (_instance == NULL) 27 | _instance = new ModuleKlass(); 28 | 29 | return _instance; 30 | } 31 | 32 | ModuleKlass::ModuleKlass() { 33 | } 34 | 35 | void ModuleKlass::initialize() { 36 | HiDict *dict = new HiDict(); 37 | set_klass_dict(dict); 38 | set_name(new HiString("module")); 39 | (new HiTypeObject())->set_own_klass(this); 40 | add_super(ObjectKlass::get_instance()); 41 | } 42 | 43 | void ModuleKlass::oops_do(OopClosure *closure, HiObject *obj) { 44 | void *temp = &(((ModuleObject *) obj)->_mod_name); 45 | closure->do_oop((HiObject **) temp); 46 | } 47 | 48 | size_t ModuleKlass::size() { 49 | return sizeof(ModuleObject); 50 | } 51 | 52 | ModuleObject::ModuleObject(HiDict *x) { 53 | set_obj_dict(x); 54 | set_klass(ModuleKlass::get_instance()); 55 | } 56 | 57 | ModuleObject *ModuleObject::import_module(HiString *cur_path, HiObject *x) { 58 | HiString *mod_name = (HiString *) x; 59 | 60 | HiList *so_list = new HiList(); 61 | so_list->append(ST(libdir_pre)); 62 | so_list->append(mod_name); 63 | so_list->append(ST(so_suf)); 64 | HiString *file_name = ST(empty)->join(so_list); 65 | 66 | // 查找so 67 | if (access(file_name->value(), R_OK) == 0) { 68 | return import_so(mod_name); 69 | } 70 | 71 | file_name = (HiString *) (mod_name->add(ST(pyc_suf))); 72 | 73 | // 从当前code的路径下查找 74 | std::string cur_path_str = cur_path->value(); 75 | std::string mod_path_str; 76 | const size_t last_slash_idx = cur_path_str.rfind('/'); 77 | if (std::string::npos != last_slash_idx) { 78 | mod_path_str = cur_path_str.substr(0, last_slash_idx); 79 | } 80 | mod_path_str = mod_path_str + "/" + file_name->value(); 81 | HiString *file_path = new HiString(mod_path_str.c_str()); 82 | 83 | if (access(file_path->value(), R_OK) == -1) { 84 | // 从/lib下查找 85 | HiList *pyc_list = new HiList(); 86 | pyc_list->append(ST(libdir_pre)); 87 | pyc_list->append(mod_name); 88 | pyc_list->append(ST(pyc_suf)); 89 | file_path = ST(empty)->join(pyc_list); 90 | } 91 | 92 | assert(access(file_path->value(), R_OK) == 0); 93 | 94 | BufferedInputStream stream(file_path->value()); 95 | BinaryFileParser parser(&stream); 96 | CodeObject *mod_code = parser.parse(); 97 | HiDict *mod_dict = Interpreter::get_instance()->run_mod(mod_code, mod_name); 98 | return new ModuleObject(mod_dict); 99 | } 100 | 101 | ModuleObject *ModuleObject::import_so(HiString *mod_name) { 102 | char *error_msg = NULL; 103 | 104 | HiString *prefix = ST(libdir_pre); 105 | HiString *so_suffix = ST(so_suf); 106 | 107 | HiString *file_name = (HiString *) (prefix->add(mod_name)->add(so_suffix)); 108 | void *handle = dlopen(file_name->value(), RTLD_NOW); 109 | if (handle == NULL) { 110 | printf("error to open file: %s\n", dlerror()); 111 | return NULL; 112 | } 113 | 114 | HiString *method_prefix = new HiString("init_"); 115 | HiString *init_meth = (HiString *) (method_prefix->add(mod_name)); 116 | INIT_FUNC init_func = (INIT_FUNC) dlsym(handle, init_meth->value()); 117 | if ((error_msg = dlerror()) != NULL) { 118 | printf("Symbol init_methods not found: %s\n", error_msg); 119 | dlclose(handle); 120 | return NULL; 121 | } 122 | 123 | RGMethod *methods = init_func(); 124 | ModuleObject *mod = new ModuleObject(new HiDict()); 125 | for (; methods->method_name != NULL; methods++) { 126 | mod->put(new HiString(methods->method_name), new FunctionObject(methods->method)); 127 | } 128 | 129 | return mod; 130 | } 131 | 132 | void ModuleObject::put(HiObject *x, HiObject *y) { 133 | obj_dict()->put(x, y); 134 | } 135 | 136 | HiObject *ModuleObject::get(HiObject *x) { 137 | return obj_dict()->get(x); 138 | } 139 | 140 | void ModuleObject::extend(ModuleObject *mo) { 141 | obj_dict()->update(mo->obj_dict()); 142 | } 143 | -------------------------------------------------------------------------------- /runtime/module.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/9/26. 3 | // 4 | 5 | #ifndef PYTHONVM_MODULE_HPP 6 | #define PYTHONVM_MODULE_HPP 7 | 8 | #include "object/hiObject.hpp" 9 | 10 | class HiDict; 11 | 12 | class OopClosure; 13 | 14 | class ModuleKlass : public Klass { 15 | private: 16 | static ModuleKlass *_instance; 17 | 18 | ModuleKlass(); 19 | 20 | public: 21 | static ModuleKlass *get_instance(); 22 | 23 | void initialize(); 24 | 25 | virtual void oops_do(OopClosure *closure, HiObject *obj); 26 | 27 | virtual size_t size(); 28 | }; 29 | 30 | class ModuleObject : public HiObject { 31 | friend class ModuleKlass; 32 | 33 | private: 34 | HiString *_mod_name; 35 | 36 | public: 37 | ModuleObject(HiDict *x); 38 | 39 | static ModuleObject *import_module(HiString *cur_path, HiObject *mod_name); 40 | 41 | static ModuleObject *import_so(HiString *mod_name); 42 | 43 | void put(HiObject *x, HiObject *y); 44 | 45 | HiObject *get(HiObject *x); 46 | 47 | void extend(ModuleObject *mo); 48 | }; 49 | 50 | #endif //PYTHONVM_MODULE_HPP 51 | -------------------------------------------------------------------------------- /runtime/stringTable.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/23. 3 | // 4 | 5 | #include "object/hiString.hpp" 6 | #include "runtime/stringTable.hpp" 7 | #include "memory/oopClosure.hpp" 8 | 9 | StringTable::StringTable() { 10 | next_str = new HiString("next"); 11 | mod_str = new HiString("__module__"); 12 | init_str = new HiString("__init__"); 13 | add_str = new HiString("__add__"); 14 | len_str = new HiString("__len__"); 15 | call_str = new HiString("__call__"); 16 | name_str = new HiString("__name__"); 17 | iter_str = new HiString("__iter__"); 18 | repr_str = new HiString("__repr__"); 19 | getitem_str = new HiString("__getitem__"); 20 | setitem_str = new HiString("__setitem__"); 21 | getattr_str = new HiString("__getattr__"); 22 | setattr_str = new HiString("__setattr__"); 23 | 24 | so_pre_str = new HiString("lib"); 25 | libdir_pre_str = new HiString("./lib/"); 26 | empty_str = new HiString(""); 27 | so_suf_str = new HiString(".dll"); 28 | pyc_suf_str = new HiString(".pyc"); 29 | } 30 | 31 | StringTable *StringTable::instance = NULL; 32 | 33 | StringTable *StringTable::get_instance() { 34 | if (instance == NULL) { 35 | instance = new StringTable(); 36 | } 37 | 38 | return instance; 39 | } 40 | 41 | void StringTable::oops_do(OopClosure *f) { 42 | f->do_oop((HiObject **) &next_str); 43 | f->do_oop((HiObject **) &mod_str); 44 | f->do_oop((HiObject **) &init_str); 45 | f->do_oop((HiObject **) &add_str); 46 | f->do_oop((HiObject **) &len_str); 47 | f->do_oop((HiObject **) &call_str); 48 | f->do_oop((HiObject **) &getitem_str); 49 | f->do_oop((HiObject **) &setitem_str); 50 | f->do_oop((HiObject **) &setattr_str); 51 | f->do_oop((HiObject **) &getattr_str); 52 | f->do_oop((HiObject **) &name_str); 53 | f->do_oop((HiObject **) &iter_str); 54 | f->do_oop((HiObject **) &repr_str); 55 | 56 | f->do_oop((HiObject **) &empty_str); 57 | f->do_oop((HiObject **) &so_suf_str); 58 | f->do_oop((HiObject **) &pyc_suf_str); 59 | f->do_oop((HiObject **) &libdir_pre_str); 60 | f->do_oop((HiObject **) &so_pre_str); 61 | } 62 | -------------------------------------------------------------------------------- /runtime/stringTable.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/23. 3 | // 4 | 5 | #ifndef PYTHONVM_STRINGTABLE_HPP 6 | #define PYTHONVM_STRINGTABLE_HPP 7 | 8 | class HiString; 9 | 10 | class OopClosure; 11 | 12 | class StringTable { 13 | private: 14 | static StringTable *instance; 15 | 16 | StringTable(); 17 | 18 | public: 19 | static StringTable *get_instance(); 20 | 21 | HiString *next_str; 22 | HiString *mod_str; 23 | HiString *init_str; 24 | HiString *add_str; 25 | HiString *len_str; 26 | HiString *call_str; 27 | HiString *getitem_str; 28 | HiString *setitem_str; 29 | HiString *getattr_str; 30 | HiString *setattr_str; 31 | HiString *name_str; 32 | HiString *iter_str; 33 | HiString *repr_str; 34 | 35 | HiString *libdir_pre_str; 36 | HiString *empty_str; 37 | HiString *so_pre_str; 38 | HiString *so_suf_str; 39 | HiString *pyc_suf_str; 40 | 41 | void oops_do(OopClosure *f); 42 | }; 43 | 44 | #endif //PYTHONVM_STRINGTABLE_HPP 45 | -------------------------------------------------------------------------------- /runtime/traceback.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/10/12. 3 | // 4 | 5 | #include "object/hiString.hpp" 6 | #include "object/hiList.hpp" 7 | #include "runtime/traceback.hpp" 8 | #include "runtime/frameObject.hpp" 9 | #include "memory/oopClosure.hpp" 10 | 11 | StackElementKlass *StackElementKlass::_instance = NULL; 12 | TracebackKlass *TracebackKlass::_instance = NULL; 13 | 14 | StackElementKlass *StackElementKlass::get_instance() { 15 | if (_instance == NULL) { 16 | _instance = new StackElementKlass(); 17 | } 18 | 19 | return _instance; 20 | } 21 | 22 | void StackElementKlass::print(HiObject *x) { 23 | StackElement *xse = (StackElement *) x; 24 | printf(" File \""); 25 | xse->_file_name->print(); 26 | printf("\", line %d,", xse->_line_no); 27 | printf(" in "); 28 | xse->_func_name->print(); 29 | printf("\n"); 30 | } 31 | 32 | size_t StackElementKlass::size() { 33 | return sizeof(StackElement); 34 | } 35 | 36 | StackElement::StackElement(HiString *file_name, 37 | HiString *func_name, 38 | int line_no) : 39 | _file_name(file_name), 40 | _func_name(func_name), 41 | _line_no(line_no) { 42 | set_klass(StackElementKlass::get_instance()); 43 | } 44 | 45 | TracebackKlass *TracebackKlass::get_instance() { 46 | if (_instance == NULL) { 47 | _instance = new TracebackKlass(); 48 | } 49 | 50 | return _instance; 51 | } 52 | 53 | void TracebackKlass::print(HiObject *x) { 54 | Traceback *tbx = (Traceback *) x; 55 | 56 | printf("Traceback (most recent call last):\n"); 57 | for (int i = tbx->_stack_elements->size() - 1; i >= 0; i--) { 58 | tbx->_stack_elements->get(i)->print(); 59 | } 60 | } 61 | 62 | void TracebackKlass::oops_do(OopClosure *f, HiObject *obj) { 63 | f->do_oop((HiObject **) &(((Traceback *) obj)->_stack_elements)); 64 | } 65 | 66 | void StackElementKlass::oops_do(OopClosure *f, HiObject *obj) { 67 | f->do_oop((HiObject **) &(((StackElement *) obj)->_file_name)); 68 | f->do_oop((HiObject **) &(((StackElement *) obj)->_func_name)); 69 | } 70 | 71 | size_t TracebackKlass::size() { 72 | return sizeof(Traceback); 73 | } 74 | 75 | Traceback::Traceback() { 76 | _stack_elements = new HiList(); 77 | set_klass(TracebackKlass::get_instance()); 78 | } 79 | 80 | void Traceback::record_frame(FrameObject *frame) { 81 | _stack_elements->append( 82 | new StackElement( 83 | frame->file_name(), 84 | frame->func_name(), 85 | frame->lineno())); 86 | } 87 | 88 | -------------------------------------------------------------------------------- /runtime/traceback.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/10/12. 3 | // 4 | 5 | #ifndef PYTHONVM_TRACEBACK_HPP 6 | #define PYTHONVM_TRACEBACK_HPP 7 | 8 | #include "object/hiObject.hpp" 9 | 10 | class HiList; 11 | class HiString; 12 | class FrameObject; 13 | 14 | class StackElementKlass : public Klass { 15 | private: 16 | StackElementKlass() {} 17 | 18 | static StackElementKlass *_instance; 19 | 20 | public: 21 | static StackElementKlass *get_instance(); 22 | 23 | virtual void print(HiObject *x); 24 | 25 | virtual size_t size(); 26 | 27 | virtual void oops_do(OopClosure *f, HiObject *obj); 28 | }; 29 | 30 | class StackElement : public HiObject { 31 | friend StackElementKlass; 32 | private: 33 | HiString *_file_name; 34 | HiString *_func_name; 35 | int _line_no; 36 | 37 | public: 38 | StackElement(HiString *fname, HiString *mname, int lineno); 39 | }; 40 | 41 | class TracebackKlass : public Klass { 42 | private: 43 | TracebackKlass() {} 44 | 45 | static TracebackKlass *_instance; 46 | 47 | public: 48 | static TracebackKlass *get_instance(); 49 | 50 | virtual void print(HiObject *x); 51 | 52 | virtual size_t size(); 53 | 54 | virtual void oops_do(OopClosure *f, HiObject *obj); 55 | }; 56 | 57 | class Traceback : public HiObject { 58 | friend class TracebackKlass; 59 | 60 | private: 61 | HiList *_stack_elements; 62 | 63 | public: 64 | Traceback(); 65 | 66 | void record_frame(FrameObject *frame); 67 | }; 68 | 69 | #endif //PYTHONVM_TRACEBACK_HPP 70 | -------------------------------------------------------------------------------- /runtime/universe.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/15. 3 | // 4 | 5 | #include "runtime/universe.hpp" 6 | #include "runtime/interpreter.hpp" 7 | #include "runtime/functionObject.hpp" 8 | #include "runtime/module.hpp" 9 | #include "object/hiInteger.hpp" 10 | #include "object/hiObject.hpp" 11 | #include "object/hiString.hpp" 12 | #include "object/hiList.hpp" 13 | #include "object/hiDict.hpp" 14 | #include "memory/heap.hpp" 15 | #include "memory/oopClosure.hpp" 16 | 17 | HiObject *Universe::HiTrue = NULL; 18 | HiObject *Universe::HiFalse = NULL; 19 | 20 | HiObject *Universe::HiNone = NULL; 21 | 22 | Heap *Universe::heap = NULL; 23 | 24 | CodeObject *Universe::main_code = NULL; 25 | 26 | HiObject *Universe::stop_iteration = NULL; 27 | ArrayList *Universe::klasses = NULL; 28 | 29 | void Universe::genesis() { 30 | heap = Heap::get_instance(); 31 | klasses = new ArrayList(); 32 | 33 | HiTrue = new HiString("True"); 34 | HiFalse = new HiString("False"); 35 | HiNone = new HiString("None"); 36 | 37 | Klass *object_klass = ObjectKlass::get_instance(); 38 | Klass *type_klass = TypeKlass::get_instance(); 39 | 40 | HiTypeObject *tp_obj = new HiTypeObject(); 41 | tp_obj->set_own_klass(type_klass); 42 | 43 | HiTypeObject *obj_obj = new HiTypeObject(); 44 | obj_obj->set_own_klass(object_klass); 45 | 46 | type_klass->add_super(object_klass); 47 | // do nothing for object klass 48 | // object_klass->add_super(NULL); 49 | 50 | IntegerKlass::get_instance()->initialize(); 51 | StringKlass::get_instance()->initialize(); 52 | DictKlass::get_instance()->initialize(); 53 | ListKlass::get_instance()->initialize(); 54 | ModuleKlass::get_instance()->initialize(); 55 | 56 | type_klass->set_klass_dict(new HiDict()); 57 | object_klass->set_klass_dict(new HiDict()); 58 | 59 | type_klass->set_name(new HiString("type")); 60 | object_klass->set_name(new HiString("object")); 61 | 62 | IntegerKlass::get_instance()->order_supers(); 63 | StringKlass::get_instance()->order_supers(); 64 | DictKlass::get_instance()->order_supers(); 65 | ListKlass::get_instance()->order_supers(); 66 | type_klass->order_supers(); 67 | 68 | FunctionKlass::get_instance()->order_supers(); 69 | NativeFunctionKlass::get_instance()->order_supers(); 70 | MethodKlass::get_instance()->order_supers(); 71 | ModuleKlass::get_instance()->order_supers(); 72 | 73 | Interpreter::get_instance()->initialize(); 74 | } 75 | 76 | void Universe::destory() {} 77 | 78 | void Universe::oops_do(OopClosure *closure) { 79 | closure->do_oop((HiObject **) &HiTrue); 80 | closure->do_oop((HiObject **) &HiFalse); 81 | closure->do_oop((HiObject **) &HiNone); 82 | 83 | closure->do_oop((HiObject **) &stop_iteration); 84 | closure->do_oop((HiObject **) &main_code); 85 | closure->do_array_list(&klasses); 86 | } 87 | -------------------------------------------------------------------------------- /runtime/universe.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/15. 3 | // 4 | 5 | #ifndef PYTHONVM_UNIVERSE_HPP 6 | #define PYTHONVM_UNIVERSE_HPP 7 | 8 | #include 9 | 10 | class Klass; 11 | class Heap; 12 | class HiInteger; 13 | class HiObject; 14 | class CodeObject; 15 | class OopClosure; 16 | 17 | template 18 | class ArrayList; 19 | 20 | class Universe { 21 | public: 22 | static HiObject *HiTrue; 23 | static HiObject *HiFalse; 24 | 25 | static HiObject *HiNone; 26 | 27 | static ArrayList *klasses; 28 | 29 | static CodeObject *main_code; 30 | 31 | static HiObject *stop_iteration; 32 | 33 | static Heap *heap; 34 | 35 | public: 36 | static void genesis(); 37 | 38 | static void destory(); 39 | 40 | static void oops_do(OopClosure *closure); 41 | }; 42 | 43 | #endif //PYTHONVM_UNIVERSE_HPP 44 | -------------------------------------------------------------------------------- /test/class1.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | value = 1 3 | 4 | a = A() 5 | print a.value -------------------------------------------------------------------------------- /test/closure.py: -------------------------------------------------------------------------------- 1 | def func(): 2 | x = 2 3 | 4 | def say(): 5 | print x 6 | 7 | return say 8 | 9 | f = func() 10 | f() 11 | -------------------------------------------------------------------------------- /test/constructor.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | def __init__(self, v): 3 | self.value = v 4 | 5 | a = A(1) 6 | print a.value 7 | -------------------------------------------------------------------------------- /test/decorator.py: -------------------------------------------------------------------------------- 1 | def call_cnt(fn): 2 | cnt = [0, ] 3 | def inner_func(*args): 4 | cnt[0] += 1 5 | print cnt[0] 6 | return fn(*args) 7 | 8 | return inner_func 9 | 10 | @call_cnt 11 | def add(a, b = 2): 12 | return a + b 13 | 14 | print add(1, 2) 15 | print add(2, 3) 16 | -------------------------------------------------------------------------------- /test/dict.py: -------------------------------------------------------------------------------- 1 | d = {1: "hello", "world": 2} 2 | print d 3 | print d[1] 4 | print d["world"] -------------------------------------------------------------------------------- /test/dict2.py: -------------------------------------------------------------------------------- 1 | # d = {1: "hello"} 2 | # d.setdefault(1, 2) 3 | # d.setdefault(2, 3) 4 | # 5 | # print d[1] 6 | # print d[2] 7 | # 8 | # d.pop(1) 9 | # print d 10 | # 11 | # del d[2] 12 | # print d 13 | 14 | d = {1: "a", 2: "b"} 15 | 16 | print d.keys() 17 | for k in d.keys(): 18 | print k, d[k] 19 | 20 | for v in d.values(): 21 | print v 22 | 23 | print d.items() 24 | for k, v in d.items(): 25 | print k, v 26 | 27 | -------------------------------------------------------------------------------- /test/dict_iterator.py: -------------------------------------------------------------------------------- 1 | d = {1: "a", 2: "b"} 2 | 3 | for k in d: 4 | print k, d[k] 5 | 6 | for k in d.iterkeys(): 7 | print k, d[k] 8 | 9 | for v in d.itervalues(): 10 | print v 11 | 12 | for k, v in d.iteritems(): 13 | print k, v -------------------------------------------------------------------------------- /test/extends.py: -------------------------------------------------------------------------------- 1 | class Z(object): 2 | def say(self): 3 | print "I am Z" 4 | 5 | class X(Z): 6 | def say(self): 7 | print "I am X" 8 | 9 | class Y(Z): 10 | def say(self): 11 | print "I am Y" 12 | 13 | class B(Y, X): 14 | def say(self): 15 | print "I am B" 16 | 17 | class A(Z): 18 | def say(self): 19 | print "I am A" 20 | pass 21 | 22 | class C(B, A): 23 | def say(self): 24 | print "I am C" 25 | 26 | c = C() 27 | c.say() 28 | 29 | c = Z() 30 | c.say() 31 | 32 | -------------------------------------------------------------------------------- /test/func.py: -------------------------------------------------------------------------------- 1 | def foo(): 2 | print "hello" 3 | return "world" 4 | 5 | print foo() 6 | -------------------------------------------------------------------------------- /test/func_bound.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | def __init__(self, v): 3 | self.value = v 4 | 5 | # bound method 6 | a = A(1) 7 | lst = [] 8 | lst.append(2) 9 | a.foo = lst.append 10 | a.foo(3) 11 | print lst 12 | 13 | #unbound method 14 | a = A(1) 15 | b = A(2) 16 | 17 | def func(self, s): 18 | print self.value 19 | print s 20 | 21 | a.bar = func 22 | A.bar = func 23 | 24 | a.bar(a, "hello") 25 | b.bar("world") 26 | -------------------------------------------------------------------------------- /test/func_def.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | def say(self): 3 | print self 4 | print "hello" 5 | 6 | a = A() 7 | a.say() -------------------------------------------------------------------------------- /test/func_default_param.py: -------------------------------------------------------------------------------- 1 | def make_func(x): 2 | def add(a, b = x): 3 | return a + b 4 | 5 | return add 6 | 7 | add5 = make_func(5) 8 | print add5(10) -------------------------------------------------------------------------------- /test/hello_if.py: -------------------------------------------------------------------------------- 1 | if 2 > 1: 2 | print 2 3 | else: 4 | print 1 5 | 6 | print 3 7 | print "end" -------------------------------------------------------------------------------- /test/hello_while.py: -------------------------------------------------------------------------------- 1 | a = 1 2 | b = 0 3 | i = 0 4 | 5 | print a 6 | print b 7 | print i 8 | 9 | while i < 10: 10 | print a 11 | t = a 12 | a = a + b 13 | b = t 14 | 15 | i = i + 1 16 | 17 | i = 0 18 | 19 | while i < 10: 20 | i = i + 1 21 | if (i > 5): 22 | break 23 | 24 | print i 25 | -------------------------------------------------------------------------------- /test/key_arg.py: -------------------------------------------------------------------------------- 1 | def foo(a, b): 2 | return a / b 3 | 4 | 5 | print foo(b=2, a=6) 6 | 7 | 8 | def sum(*args): 9 | t = 0 10 | for i in args: 11 | t += i 12 | 13 | return t 14 | 15 | 16 | print sum(1, 2, 3, 4) 17 | 18 | 19 | def foo(**kwargs): 20 | for k, v in kwargs.iteritems(): 21 | print k 22 | print v 23 | 24 | 25 | foo(a=1, b=2) 26 | -------------------------------------------------------------------------------- /test/list.py: -------------------------------------------------------------------------------- 1 | l = [4 ,1, 2, 3] 2 | print l 3 | 4 | l.remove(2) 5 | print l 6 | 7 | l[0] = 3 8 | print l 9 | 10 | del l[0] 11 | print l 12 | 13 | print l.pop() 14 | print l -------------------------------------------------------------------------------- /test/list_append.py: -------------------------------------------------------------------------------- 1 | lst = [1, 2] 2 | lst.append(0) 3 | print lst 4 | -------------------------------------------------------------------------------- /test/list_contains.py: -------------------------------------------------------------------------------- 1 | l = ["hello", "world"] 2 | 3 | if "hello" in l: 4 | print "yes" 5 | else: 6 | print "no" 7 | 8 | if "lo" in "hello": 9 | print "yes" 10 | else: 11 | print "no" -------------------------------------------------------------------------------- /test/list_insert.py: -------------------------------------------------------------------------------- 1 | l = [1, 2] 2 | l.insert(0, 3) 3 | print l -------------------------------------------------------------------------------- /test/list_iterator.py: -------------------------------------------------------------------------------- 1 | list = [1, 2, 3] 2 | for i in list: 3 | print i -------------------------------------------------------------------------------- /test/list_modify.py: -------------------------------------------------------------------------------- 1 | list = [1, 2] 2 | list[0] = 3 3 | 4 | print list -------------------------------------------------------------------------------- /test/list_plus.py: -------------------------------------------------------------------------------- 1 | a = [1 ,2] 2 | b = ["hello", "world"] 3 | c = a + b 4 | print a 5 | print b 6 | print c 7 | 8 | d = c * 2 9 | print d -------------------------------------------------------------------------------- /test/list_sort.py: -------------------------------------------------------------------------------- 1 | t = ["a", 2, "c", 1, "b", 3, [1, 2], [3, 4]] 2 | t.sort() 3 | 4 | print t -------------------------------------------------------------------------------- /test/list_subscr.py: -------------------------------------------------------------------------------- 1 | lst = ["hello", "world"] 2 | print lst[0] 3 | 4 | str = "hello" 5 | 6 | print str[0] -------------------------------------------------------------------------------- /test/method.py: -------------------------------------------------------------------------------- 1 | s = "hello" 2 | t = s.upper() 3 | 4 | print s 5 | print t -------------------------------------------------------------------------------- /test/native_func.py: -------------------------------------------------------------------------------- 1 | s = "hello" 2 | print len(s) 3 | 4 | def py_len(o): 5 | return len(o) 6 | 7 | print py_len(s) -------------------------------------------------------------------------------- /test/none.py: -------------------------------------------------------------------------------- 1 | print None -------------------------------------------------------------------------------- /test/object_instance.py: -------------------------------------------------------------------------------- 1 | a = int() 2 | print a 3 | b = str() 4 | print b 5 | c = list() 6 | print c 7 | d = dict() 8 | print d -------------------------------------------------------------------------------- /test/object_prop.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | value = 1 3 | 4 | a = A() 5 | print a.value 6 | 7 | a.field = "hello" 8 | 9 | print a.field 10 | -------------------------------------------------------------------------------- /test/op_overload1.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | def __init__(self, v): 3 | self.value = v 4 | 5 | def __add__(self, other): 6 | print "exec operator +" 7 | return A(self.value + other.value) 8 | 9 | a = A(1) 10 | b = A(2) 11 | c = a + b 12 | 13 | print c.value -------------------------------------------------------------------------------- /test/op_overload2.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | def __len__(self): 3 | print "len() called" 4 | return 1 5 | 6 | a = A() 7 | print len(a) -------------------------------------------------------------------------------- /test/op_overload3.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | def __init__(self, v): 3 | self.value = v 4 | 5 | def __call__(self, a): 6 | if self.value > a.value: 7 | print "gt" 8 | elif self.value < a.value: 9 | print "lt" 10 | elif self.value == a.value: 11 | print "eq" 12 | else: 13 | print "can not compare" 14 | 15 | a = A(1) 16 | b = A(2) 17 | c = A(0) 18 | 19 | a(b) 20 | a(a) 21 | a(c) -------------------------------------------------------------------------------- /test/op_overload4.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | def __getitem__(self, key): 3 | if key == "hello": 4 | return "hi" 5 | elif key == "how are you": 6 | return "fine" 7 | 8 | def __setitem__(self, key, value): 9 | print self 10 | print key 11 | print value 12 | 13 | a = A() 14 | print a["hello"] 15 | print a["how are you"] 16 | a["one"] = 1 -------------------------------------------------------------------------------- /test/op_overload5.py: -------------------------------------------------------------------------------- 1 | keys = [] 2 | values = [] 3 | 4 | class B(object): 5 | def __setattr__(self, k, v): 6 | if k in keys: 7 | index = keys.index(k) 8 | values[index] = v 9 | else: 10 | keys.append(k) 11 | values.append(v) 12 | 13 | def __getattr__(self, k): 14 | if k in keys: 15 | index = keys.index(k) 16 | return values[index] 17 | else: 18 | return None 19 | 20 | b = B() 21 | b.foo = 1 22 | b.bar = 2 23 | print b.foo 24 | print b.bar 25 | b.foo = 3 26 | print b.foo -------------------------------------------------------------------------------- /test/test_break.py: -------------------------------------------------------------------------------- 1 | i = 0 2 | while i < 10: 3 | try: 4 | i += 1 5 | if i == 5: 6 | break 7 | print i 8 | finally: 9 | print "hello" 10 | -------------------------------------------------------------------------------- /test/test_builtin_lib.py: -------------------------------------------------------------------------------- 1 | print range(3) -------------------------------------------------------------------------------- /test/test_continue.py: -------------------------------------------------------------------------------- 1 | i = 0 2 | while i < 5: 3 | try: 4 | i += 1 5 | if i > 3: 6 | continue 7 | print i 8 | finally: 9 | print "hello" 10 | -------------------------------------------------------------------------------- /test/test_coroutine.py: -------------------------------------------------------------------------------- 1 | # Two simple generator functions 2 | def countdown(n): 3 | while n > 0: 4 | print('T-minus', n) 5 | yield 6 | n -= 1 7 | print('Blastoff!') 8 | 9 | 10 | def countup(n): 11 | x = 0 12 | while x < n: 13 | print('Counting up', x) 14 | yield 15 | x += 1 16 | 17 | 18 | class TaskScheduler: 19 | def __init__(self): 20 | self._task_queue = [] 21 | 22 | def new_task(self, task): 23 | ''' 24 | Admit a newly started task to the scheduler 25 | ''' 26 | self._task_queue.append(task) 27 | 28 | def run(self): 29 | ''' 30 | Run until there are no more tasks 31 | ''' 32 | while len(self._task_queue) > 0: 33 | task = self._task_queue.popleft() 34 | try: 35 | # Run until the next yield statement 36 | task.next() 37 | self._task_queue.append(task) 38 | except StopIteration: 39 | # Generator is no longer executing 40 | pass 41 | 42 | 43 | # Example use 44 | sched = TaskScheduler() 45 | sched.new_task(countdown(2)) 46 | sched.new_task(countup(5)) 47 | sched.run() 48 | -------------------------------------------------------------------------------- /test/test_exception.py: -------------------------------------------------------------------------------- 1 | try: 2 | raise Exception("something wrong") 3 | except Exception, e: 4 | print e 5 | 6 | try: 7 | raise StopIteration("end of iteration") 8 | except ZeroDivisionError, e: 9 | print "handled" 10 | except Exception, e: 11 | print e 12 | -------------------------------------------------------------------------------- /test/test_exception_trace.py: -------------------------------------------------------------------------------- 1 | def foo(a): 2 | b = a - 1 3 | bar(a, b) 4 | 5 | 6 | def bar(a, b): 7 | raise Exception("something wrong") 8 | 9 | 10 | foo(1) 11 | -------------------------------------------------------------------------------- /test/test_finally.py: -------------------------------------------------------------------------------- 1 | def foo(): 2 | try: 3 | print "hello" 4 | return 5 | print "hi" 6 | finally: 7 | print "world" 8 | 9 | 10 | foo() 11 | -------------------------------------------------------------------------------- /test/test_func.py: -------------------------------------------------------------------------------- 1 | def fact(n): 2 | if n == 1: 3 | return 1 4 | else: 5 | return fact(n-1) * n -------------------------------------------------------------------------------- /test/test_gc1.py: -------------------------------------------------------------------------------- 1 | i = 0 2 | while i < 21474826: 3 | i = i + 1 4 | if i % 1000000 == 0: 5 | print i -------------------------------------------------------------------------------- /test/test_generator.py: -------------------------------------------------------------------------------- 1 | def foo(): 2 | i = 0 3 | while i < 10: 4 | yield i 5 | i += 1 6 | 7 | return 8 | 9 | 10 | for i in foo(): 11 | print i 12 | 13 | 14 | def func(): 15 | i = 0 16 | while i < 2: 17 | yield i 18 | i += 1 19 | 20 | return 21 | 22 | 23 | g = func() 24 | print g.next() 25 | print g.next() 26 | print g.next() 27 | -------------------------------------------------------------------------------- /test/test_global.py: -------------------------------------------------------------------------------- 1 | global x 2 | x = 0 3 | 4 | def func(): 5 | global x 6 | x = 1 7 | 8 | func() 9 | print x -------------------------------------------------------------------------------- /test/test_global2.py: -------------------------------------------------------------------------------- 1 | def foo(): 2 | return 3 | 4 | if foo() is None: 5 | print True 6 | -------------------------------------------------------------------------------- /test/test_import.py: -------------------------------------------------------------------------------- 1 | # import test_func 2 | from test_func import fact 3 | 4 | print fact(5) 5 | -------------------------------------------------------------------------------- /test/test_iter_fib.py: -------------------------------------------------------------------------------- 1 | class Fib(object): 2 | def __init__(self, n): 3 | self.n = n 4 | 5 | def __iter__(self): 6 | return FibIterator(self.n) 7 | 8 | 9 | class FibIterator(object): 10 | def __init__(self, n): 11 | self.n = n 12 | self.a = 1 13 | self.b = 1 14 | self.cnt = 0 15 | 16 | def next(self): 17 | if (self.cnt > self.n): 18 | raise StopIteration 19 | 20 | self.cnt += 1 21 | t = self.a 22 | self.a = self.a + self.b 23 | self.b = t 24 | return t 25 | 26 | 27 | fib = Fib(10) 28 | itor = iter(fib) 29 | 30 | for i in fib: 31 | print i 32 | 33 | while True: 34 | try: 35 | print itor.next() 36 | except StopIteration, e: 37 | break -------------------------------------------------------------------------------- /test/test_param.py: -------------------------------------------------------------------------------- 1 | def add(a, b): 2 | return a + b 3 | 4 | print add(1, 2) -------------------------------------------------------------------------------- /test/test_so.py: -------------------------------------------------------------------------------- 1 | import libmath 2 | 3 | print libmath.add(1, 2) -------------------------------------------------------------------------------- /test/type_object.py: -------------------------------------------------------------------------------- 1 | print list 2 | 3 | t = type(1) 4 | print t 5 | print type(t) 6 | 7 | i = 0 8 | while i < 5: 9 | t = type(t) 10 | print t 11 | i = i + 1 -------------------------------------------------------------------------------- /test/type_prop.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | def __init__(self, v): 3 | self.value = v 4 | 5 | a = A(1) 6 | b = A(2) 7 | print a.value 8 | 9 | a.field = 3 10 | A.field = 4 11 | print a.field 12 | 13 | print b.field 14 | -------------------------------------------------------------------------------- /util/arrayList.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/14. 3 | // 4 | #include 5 | 6 | #include "util/arrayList.hpp" 7 | #include "object/hiObject.hpp" 8 | #include "runtime/universe.hpp" 9 | #include "memory/heap.hpp" 10 | #include "memory/oopClosure.hpp" 11 | 12 | template 13 | ArrayList::ArrayList(int n) { 14 | _length = n; 15 | _size = 0; 16 | // _array = new T[n]; 17 | void *temp = Universe::heap->allocate(sizeof(T) * n); 18 | _array = new(temp)T[n]; 19 | } 20 | 21 | template 22 | void ArrayList::add(T t) { 23 | if (_size >= _length) 24 | expand(); 25 | 26 | _array[_size++] = t; 27 | } 28 | 29 | template 30 | void ArrayList::insert(int index, T t) { 31 | add(NULL); 32 | for (int i = _size - 1; i > index; i--) { 33 | _array[i] = _array[i - 1]; 34 | } 35 | 36 | _array[index] = t; 37 | } 38 | 39 | template 40 | void ArrayList::expand() { 41 | // T *new_array = new T[_length << 1]; 42 | void *temp = Universe::heap->allocate(sizeof(T) * (_length << 1)); 43 | T *new_array = new (temp)T[_length << 1]; 44 | 45 | for (int i = 0; i < _length; ++i) { 46 | new_array[i] = _array[i]; 47 | } 48 | 49 | // we do not rely on this, but gc. 50 | // delete[] _array; 51 | _array = new_array; 52 | 53 | _length <<= 1; 54 | // printf("expand an array to %d, size is %d\n", _length, _size); 55 | } 56 | 57 | template 58 | int ArrayList::size() { 59 | return _size; 60 | } 61 | 62 | template 63 | int ArrayList::length() { 64 | return _length; 65 | } 66 | 67 | template 68 | T ArrayList::get(int index) { 69 | return _array[index]; 70 | } 71 | 72 | template 73 | void ArrayList::set(int index, T t) { 74 | if (_size <= index) { 75 | _size = index + 1; 76 | } 77 | 78 | while (_size > _length) { 79 | expand(); 80 | } 81 | 82 | _array[index] = t; 83 | } 84 | 85 | template 86 | T ArrayList::pop() { 87 | return _array[--_size]; 88 | } 89 | 90 | template 91 | void ArrayList::delete_index(int index) { 92 | for (int i = index; i < _size - 1; ++i) { 93 | _array[i] = _array[i + 1]; 94 | } 95 | 96 | _size--; 97 | } 98 | 99 | template 100 | int ArrayList::index(T t) { 101 | return 0; 102 | } 103 | 104 | template<> 105 | int ArrayList::index(HiObject *t) { 106 | for (int i = 0; i < _size; i++) { 107 | if (_array[i]->equal(t) == Universe::HiTrue) { 108 | return i; 109 | } 110 | } 111 | 112 | return -1; 113 | } 114 | 115 | template 116 | void *ArrayList::operator new(size_t size) { 117 | return Universe::heap->allocate(size); 118 | } 119 | 120 | template 121 | void ArrayList::oops_do(OopClosure *closure) { 122 | closure->do_raw_mem((char **) (&_array), 123 | _length * sizeof(T)); 124 | } 125 | 126 | template<> 127 | void ArrayList::oops_do(OopClosure *closure) { 128 | closure->do_raw_mem((char **) (&_array), 129 | _length * sizeof(Klass *)); 130 | 131 | for (int i = 0; i < size(); i++) { 132 | closure->do_klass((Klass **) &_array[i]); 133 | } 134 | } 135 | 136 | template<> 137 | void ArrayList::oops_do(OopClosure *closure) { 138 | closure->do_raw_mem((char **) (&_array), 139 | _length * sizeof(HiObject *)); 140 | 141 | for (int i = 0; i < size(); i++) { 142 | closure->do_oop((HiObject **) &_array[i]); 143 | } 144 | } 145 | 146 | class HiObject; 147 | template class ArrayList; 148 | 149 | class HiString; 150 | template class ArrayList; 151 | 152 | class Block; 153 | template class ArrayList; 154 | 155 | class Klass; 156 | template class ArrayList; -------------------------------------------------------------------------------- /util/arrayList.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/14. 3 | // 4 | 5 | #ifndef PYTHONVM_ARRAYLIST_HPP 6 | #define PYTHONVM_ARRAYLIST_HPP 7 | 8 | #include 9 | 10 | class OopClosure; 11 | 12 | template 13 | class ArrayList { 14 | private: 15 | int _length; 16 | T *_array; 17 | int _size; 18 | 19 | void expand(); 20 | 21 | public: 22 | ArrayList(int n = 8); 23 | 24 | void add(T t); 25 | 26 | void insert(int index, T t); 27 | 28 | T get(int index); 29 | 30 | void set(int index, T t); 31 | 32 | int size(); 33 | 34 | int length(); 35 | 36 | int index(T t); 37 | 38 | T *value() { return _array; } 39 | 40 | T pop(); 41 | 42 | void delete_index(int index); 43 | 44 | void *operator new(size_t size); 45 | 46 | void oops_do(OopClosure *closure); 47 | }; 48 | 49 | class HiObject; 50 | typedef ArrayList *ObjList; 51 | 52 | #endif //PYTHONVM_ARRAYLIST_HPP 53 | -------------------------------------------------------------------------------- /util/bufferedInputStream.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/14. 3 | // 4 | 5 | #ifndef PYTHONVM_BUFFEREDINPUTSTREAM_HPP 6 | #define PYTHONVM_BUFFEREDINPUTSTREAM_HPP 7 | 8 | #include 9 | 10 | #define BUFFER_LEN 256 11 | 12 | class BufferedInputStream { 13 | private: 14 | FILE *fp; 15 | const char *file_path; 16 | char szBuffer[BUFFER_LEN]; 17 | unsigned short index; 18 | 19 | public: 20 | BufferedInputStream(char const *file_path) { 21 | fp = fopen(file_path, "rb"); 22 | this->file_path = file_path; 23 | fread(szBuffer, BUFFER_LEN * sizeof(char), 1, fp); 24 | index = 0; 25 | } 26 | 27 | ~BufferedInputStream() { 28 | close(); 29 | } 30 | 31 | const char *get_file_path() { 32 | return file_path; 33 | } 34 | 35 | char read() { 36 | if (index < BUFFER_LEN) 37 | return szBuffer[index++]; 38 | else { 39 | index = 0; 40 | fread(szBuffer, BUFFER_LEN * sizeof(char), 1, fp); 41 | return szBuffer[index++]; 42 | } 43 | } 44 | 45 | int read_int() { 46 | int b1 = read() & 0xff; 47 | int b2 = read() & 0xff; 48 | int b3 = read() & 0xff; 49 | int b4 = read() & 0xff; 50 | 51 | return b4 << 24 | b3 << 16 | b2 << 8 | b1; 52 | } 53 | 54 | double read_double() { 55 | char t[8]; 56 | for (int i = 0; i < 8; i++) { 57 | t[i] = read(); 58 | } 59 | 60 | return *(double *) t; 61 | } 62 | 63 | void unread() { 64 | index--; 65 | } 66 | 67 | void close() { 68 | if (fp != NULL) { 69 | fclose(fp); 70 | fp = NULL; 71 | } 72 | } 73 | }; 74 | 75 | 76 | #endif //PYTHONVM_BUFFEREDINPUTSTREAM_HPP 77 | -------------------------------------------------------------------------------- /util/handles.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/10/13. 3 | // 4 | 5 | #include "util/handles.hpp" 6 | #include "memory/oopClosure.hpp" 7 | 8 | #include 9 | 10 | HandleMark *HandleMark::instance = NULL; 11 | 12 | HandleMark::HandleMark() { 13 | _head = 0x0; 14 | } 15 | 16 | HandleMark *HandleMark::get_instance() { 17 | if (!instance) 18 | instance = new HandleMark(); 19 | 20 | return instance; 21 | } 22 | 23 | void HandleMark::oops_do(OopClosure *f) { 24 | Handle *cur = _head; 25 | while (cur) { 26 | cur->oops_do(f); 27 | cur = cur->_next; 28 | } 29 | } 30 | 31 | Handle::Handle(HiObject *t) { 32 | _value = t; 33 | 34 | _next = HandleMark::get_instance()->head(); 35 | HandleMark::get_instance()->set_head(this); 36 | } 37 | 38 | Handle::~Handle() { 39 | _value = 0x0; 40 | 41 | HandleMark::get_instance()->set_head(_next); 42 | _next = 0x0; 43 | } 44 | 45 | HiObject *Handle::operator->() { 46 | return _value; 47 | } 48 | 49 | void Handle::oops_do(OopClosure *f) { 50 | f->do_oop(&_value); 51 | } 52 | 53 | HiObject *Handle::resolve() { 54 | return _value; 55 | } 56 | -------------------------------------------------------------------------------- /util/handles.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/10/13. 3 | // 4 | 5 | #ifndef PYTHONVM_HANDLES_HPP 6 | #define PYTHONVM_HANDLES_HPP 7 | 8 | class HiObject; 9 | 10 | class OopClosure; 11 | 12 | class Handle { 13 | friend class HandleMark; 14 | 15 | private: 16 | HiObject *_value; 17 | Handle *_next; 18 | 19 | public: 20 | Handle(HiObject *t); 21 | 22 | ~Handle(); 23 | 24 | void oops_do(OopClosure *f); 25 | 26 | HiObject *operator->(); 27 | 28 | HiObject *operator()() { return _value; } 29 | 30 | HiObject *resolve(); 31 | }; 32 | 33 | class HandleMark { 34 | private: 35 | static HandleMark *instance; 36 | Handle *_head; 37 | 38 | public: 39 | HandleMark(); 40 | 41 | static HandleMark *get_instance(); 42 | 43 | void oops_do(OopClosure *f); 44 | 45 | Handle *head() { return _head; } 46 | 47 | void set_head(Handle *x) { _head = x; } 48 | }; 49 | 50 | #endif //PYTHONVM_HANDLES_HPP 51 | -------------------------------------------------------------------------------- /util/map.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/16. 3 | // 4 | 5 | #include "util/map.hpp" 6 | #include "runtime/universe.hpp" 7 | #include "object/hiObject.hpp" 8 | #include "memory/heap.hpp" 9 | #include "memory/oopClosure.hpp" 10 | 11 | template 12 | Map::Map() { 13 | _entries = new MapEntry[8]; 14 | _length = 8; 15 | _size = 0; 16 | } 17 | 18 | template 19 | MapEntry::MapEntry(const MapEntry &entry) { 20 | _k = entry._k; 21 | _v = entry._v; 22 | } 23 | 24 | template 25 | void Map::put(K k, V v) { 26 | for (int i = 0; i < _size; ++i) { 27 | if (_entries[i]._k->equal(k) == (HiObject *) Universe::HiTrue) { 28 | _entries[i]._v = v; 29 | return; 30 | } 31 | } 32 | 33 | expand(); 34 | _entries[_size++] = MapEntry(k, v); 35 | } 36 | 37 | template 38 | V Map::get(K k) { 39 | int i = index(k); 40 | if (i < 0) { 41 | return Universe::HiNone; 42 | } else { 43 | return _entries[i]._v; 44 | } 45 | } 46 | 47 | template 48 | K Map::get_key(int index) { 49 | return _entries[index]._k; 50 | } 51 | 52 | template 53 | V Map::get_value(int index) { 54 | return _entries[index]._v; 55 | } 56 | 57 | template 58 | bool Map::has_key(K k) { 59 | int i = index(k); 60 | return i >= 0; 61 | } 62 | 63 | template 64 | V Map::remove(K k) { 65 | int i = index(k); 66 | 67 | if (i < 0) { 68 | return 0; 69 | } 70 | 71 | V v = _entries[i]._v; 72 | _entries[i] = _entries[--_size]; 73 | return v; 74 | } 75 | 76 | template 77 | int Map::index(K k) { 78 | for (int i = 0; i < _size; i++) { 79 | if (_entries[i]._k->equal(k) == (HiObject *) Universe::HiTrue) { 80 | return i; 81 | } 82 | } 83 | 84 | return -1; 85 | } 86 | 87 | template 88 | void Map::expand() { 89 | if (_size >= _length) { 90 | MapEntry *new_entries = new MapEntry[_length << 1]; 91 | for (int i = 0; i < _size; i++) { 92 | new_entries[i] = _entries[i]; 93 | } 94 | _length <<= 1; 95 | // delete[] _entries; 96 | _entries = new_entries; 97 | } 98 | } 99 | 100 | template 101 | void *MapEntry::operator new[](size_t size) { 102 | return Universe::heap->allocate(size); 103 | } 104 | 105 | template 106 | void *Map::operator new(size_t size) { 107 | return Universe::heap->allocate(size); 108 | } 109 | 110 | template 111 | void Map::oops_do(OopClosure *closure) { 112 | closure->do_raw_mem((char **) (&_entries), 113 | _length * sizeof(MapEntry)); 114 | for (int i = 0; i < _size; i++) { 115 | closure->do_oop(&(_entries[i]._k)); 116 | closure->do_oop(&(_entries[i]._v)); 117 | } 118 | } 119 | 120 | template 121 | class Map; -------------------------------------------------------------------------------- /util/map.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/8/16. 3 | // 4 | 5 | #ifndef PYTHONVM_MAP_HPP 6 | #define PYTHONVM_MAP_HPP 7 | 8 | #include 9 | 10 | class OopClosure; 11 | 12 | template 13 | class MapEntry { 14 | public: 15 | K _k; 16 | V _v; 17 | 18 | MapEntry(const MapEntry &entry); 19 | 20 | MapEntry(K k, V v) : _k(k), _v(v) {} 21 | 22 | MapEntry() : _k(0), _v(0) {} 23 | 24 | void *operator new[](size_t size); 25 | }; 26 | 27 | template 28 | class Map { 29 | private: 30 | MapEntry *_entries; 31 | int _size; 32 | int _length; 33 | 34 | void expand(); 35 | 36 | public: 37 | Map(); 38 | 39 | int size() { return _size; } 40 | 41 | void put(K k, V v); 42 | 43 | V get(K k); 44 | 45 | K get_key(int index); 46 | 47 | V get_value(int index); 48 | 49 | bool has_key(K k); 50 | 51 | V remove(K k); 52 | 53 | int index(K k); 54 | 55 | MapEntry *entries() { return _entries; } 56 | 57 | void *operator new(size_t size); 58 | 59 | void oops_do(OopClosure *closure); 60 | }; 61 | 62 | #endif //PYTHONVM_MAP_HPP 63 | -------------------------------------------------------------------------------- /util/stack.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/9/18. 3 | // 4 | 5 | #include "util/stack.hpp" 6 | 7 | template<> 8 | void Stack::oops_do(OopClosure *f) { 9 | for (int i = 0; i < _len; i++) { 10 | f->do_oop(&vector[i]); 11 | } 12 | } 13 | 14 | template 15 | void Stack::copy(const Stack *stack) { 16 | _size = stack->_size; 17 | _len = stack->_len; 18 | for (int i = 0; i < _size; i++) { 19 | vector[i] = stack->vector[i]; 20 | } 21 | } 22 | 23 | template 24 | class Stack; -------------------------------------------------------------------------------- /util/stack.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kosho on 2020/9/18. 3 | // 4 | 5 | #ifndef PYTHONVM_STACK_HPP 6 | #define PYTHONVM_STACK_HPP 7 | 8 | // 主要用于gc dfs, 在堆外分配对象 9 | template 10 | class Stack { 11 | private: 12 | V *vector; 13 | int _len; 14 | int _size; 15 | 16 | public: 17 | Stack(int n = 16) { 18 | _len = n; 19 | vector = new V[n]; 20 | _size = 0; 21 | } 22 | 23 | ~Stack() { 24 | delete[] vector; 25 | _len = 0; 26 | _size = 0; 27 | } 28 | 29 | void push(V v) { 30 | vector[_size++] = v; 31 | } 32 | 33 | V pop() { 34 | return vector[--_size]; 35 | } 36 | 37 | V top() { 38 | return vector[_size - 1]; 39 | } 40 | 41 | V peek(int index) { 42 | return vector[_size - index - 1]; 43 | } 44 | 45 | int len() { 46 | return _len; 47 | } 48 | 49 | int size() { 50 | return _size; 51 | } 52 | 53 | bool empty() { 54 | return _size == 0; 55 | } 56 | 57 | void copy(const Stack *stack); 58 | 59 | void oops_do(OopClosure *f); 60 | }; 61 | 62 | #endif //PYTHONVM_STACK_HPP 63 | --------------------------------------------------------------------------------