mirror of
				https://github.com/pocketpy/pocketpy
				synced 2025-10-30 08:20:16 +00:00 
			
		
		
		
	Compare commits
	
		
			No commits in common. "b8fc853cb8fa41d1cd41fd07aa1480d2ad3eac65" and "79012a6b08df3aafe9728c8c8740272c94fdfa2b" have entirely different histories.
		
	
	
		
			b8fc853cb8
			...
			79012a6b08
		
	
		
| @ -42,22 +42,20 @@ void c11_string__ctor2(c11_string* self, const char* data, int size); | |||||||
| c11_string* c11_string__copy(c11_string* self); | c11_string* c11_string__copy(c11_string* self); | ||||||
| void c11_string__delete(c11_string* self); | void c11_string__delete(c11_string* self); | ||||||
| c11_sv c11_string__sv(c11_string* self); | c11_sv c11_string__sv(c11_string* self); | ||||||
|  | c11_string* c11_string__replace(c11_string* self, char old, char new_); | ||||||
| 
 | 
 | ||||||
| int c11_sv__u8_length(c11_sv self); | int c11_string__u8_length(c11_string* self); | ||||||
| c11_sv c11_sv__u8_getitem(c11_sv self, int i); | c11_sv c11_string__u8_getitem(c11_string* self, int i); | ||||||
| c11_string* c11_sv__u8_slice(c11_sv self, int start, int stop, int step); | c11_string* c11_string__u8_slice(c11_string* self, int start, int stop, int step); | ||||||
| 
 | 
 | ||||||
| // general string operations
 | // general string operations
 | ||||||
| c11_sv c11_sv__slice(c11_sv sv, int start); | c11_sv c11_sv__slice(c11_sv sv, int start); | ||||||
| c11_sv c11_sv__slice2(c11_sv sv, int start, int stop); | c11_sv c11_sv__slice2(c11_sv sv, int start, int stop); | ||||||
| c11_sv c11_sv__strip(c11_sv sv, c11_sv chars, bool left, bool right); | c11_sv c11_sv__strip(c11_sv sv, bool left, bool right); | ||||||
| int c11_sv__index(c11_sv self, char c); | int c11_sv__index(c11_sv self, char c); | ||||||
| int c11_sv__index2(c11_sv self, c11_sv sub, int start); | int c11_sv__index2(c11_sv self, c11_sv sub, int start); | ||||||
| int c11_sv__count(c11_sv self, c11_sv sub); | int c11_sv__count(c11_sv self, c11_sv sub); | ||||||
| 
 | 
 | ||||||
| c11_string* c11_sv__replace(c11_sv self, char old, char new_); |  | ||||||
| c11_string* c11_sv__replace2(c11_sv self, c11_sv old, c11_sv new_); |  | ||||||
| 
 |  | ||||||
| c11_vector/* T=c11_sv */ c11_sv__split(c11_sv self, char sep); | c11_vector/* T=c11_sv */ c11_sv__split(c11_sv self, char sep); | ||||||
| c11_vector/* T=c11_sv */ c11_sv__split2(c11_sv self, c11_sv sep); | c11_vector/* T=c11_sv */ c11_sv__split2(c11_sv self, c11_sv sep); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -70,9 +70,6 @@ void pk_VM__dtor(pk_VM* self); | |||||||
| void pk_VM__push_frame(pk_VM* self, Frame* frame); | void pk_VM__push_frame(pk_VM* self, Frame* frame); | ||||||
| void pk_VM__pop_frame(pk_VM* self); | void pk_VM__pop_frame(pk_VM* self); | ||||||
| 
 | 
 | ||||||
| bool pk__parse_int_slice(const py_Ref slice, int length, int* start, int* stop, int* step); |  | ||||||
| bool pk__normalize_index(int* index, int length); |  | ||||||
| 
 |  | ||||||
| typedef enum pk_FrameResult { | typedef enum pk_FrameResult { | ||||||
|     RES_RETURN, |     RES_RETURN, | ||||||
|     RES_CALL, |     RES_CALL, | ||||||
| @ -96,7 +93,6 @@ const char* pk_opname(Opcode op); | |||||||
| void pk_object__register(); | void pk_object__register(); | ||||||
| void pk_number__register(); | void pk_number__register(); | ||||||
| py_Type pk_str__register(); | py_Type pk_str__register(); | ||||||
| py_Type pk_str_iterator__register(); |  | ||||||
| py_Type pk_bytes__register(); | py_Type pk_bytes__register(); | ||||||
| py_Type pk_list__register(); | py_Type pk_list__register(); | ||||||
| py_Type pk_function__register(); | py_Type pk_function__register(); | ||||||
|  | |||||||
| @ -244,8 +244,6 @@ void py_formatexc(char* out); | |||||||
| #define TypeError(...) py_exception("TypeError", __VA_ARGS__) | #define TypeError(...) py_exception("TypeError", __VA_ARGS__) | ||||||
| #define ValueError(...) py_exception("ValueError", __VA_ARGS__) | #define ValueError(...) py_exception("ValueError", __VA_ARGS__) | ||||||
| #define IndexError(...) py_exception("IndexError", __VA_ARGS__) | #define IndexError(...) py_exception("IndexError", __VA_ARGS__) | ||||||
| #define StopIteration() py_exception("StopIteration", "") |  | ||||||
| #define NotImplementedError() py_exception("NotImplementedError", "") |  | ||||||
| #define AttributeError(self, n)                                                                    \ | #define AttributeError(self, n)                                                                    \ | ||||||
|     py_exception("AttributeError", "'%t' object has no attribute '%n'", (self)->type, (n)) |     py_exception("AttributeError", "'%t' object has no attribute '%n'", (self)->type, (n)) | ||||||
| #define UnboundLocalError(n)                                                                       \ | #define UnboundLocalError(n)                                                                       \ | ||||||
| @ -266,12 +264,6 @@ int py_gt(const py_Ref, const py_Ref); | |||||||
| 
 | 
 | ||||||
| bool py_hash(const py_Ref, py_i64* out); | bool py_hash(const py_Ref, py_i64* out); | ||||||
| 
 | 
 | ||||||
| /// Get the iterator of the object.
 |  | ||||||
| bool py_iter(const py_Ref); |  | ||||||
| /// Get the next element from the iterator.
 |  | ||||||
| /// 1: success, 0: StopIteration, -1: error
 |  | ||||||
| int py_next(const py_Ref); |  | ||||||
| 
 |  | ||||||
| /// Python equivalent to `lhs is rhs`.
 | /// Python equivalent to `lhs is rhs`.
 | ||||||
| bool py_isidentical(const py_Ref, const py_Ref); | bool py_isidentical(const py_Ref, const py_Ref); | ||||||
| 
 | 
 | ||||||
| @ -304,7 +296,6 @@ bool py_str(py_Ref val); | |||||||
| py_GlobalRef py_retval(); | py_GlobalRef py_retval(); | ||||||
| 
 | 
 | ||||||
| #define py_isnil(self) ((self)->type == 0) | #define py_isnil(self) ((self)->type == 0) | ||||||
| #define py_isnone(self) ((self)->type == tp_none_type) |  | ||||||
| 
 | 
 | ||||||
| /* tuple */ | /* tuple */ | ||||||
| 
 | 
 | ||||||
| @ -340,17 +331,9 @@ py_GlobalRef py_tpobject(py_Type type); | |||||||
| /// Get the type name.
 | /// Get the type name.
 | ||||||
| const char* py_tpname(py_Type type); | const char* py_tpname(py_Type type); | ||||||
| 
 | 
 | ||||||
| /// Call a type to create a new instance.
 |  | ||||||
| bool py_tpcall(py_Type type, int argc, py_Ref argv); |  | ||||||
| 
 |  | ||||||
| /// Check if the object is an instance of the given type.
 | /// Check if the object is an instance of the given type.
 | ||||||
| bool py_checktype(const py_Ref self, py_Type type); | bool py_checktype(const py_Ref self, py_Type type); | ||||||
| 
 | 
 | ||||||
| #define py_checkint(self) py_checktype(self, tp_int) |  | ||||||
| #define py_checkfloat(self) py_checktype(self, tp_float) |  | ||||||
| #define py_checkbool(self) py_checktype(self, tp_bool) |  | ||||||
| #define py_checkstr(self) py_checktype(self, tp_str) |  | ||||||
| 
 |  | ||||||
| int py_replinput(char* buf); | int py_replinput(char* buf); | ||||||
| 
 | 
 | ||||||
| /// Python favored string formatting.
 | /// Python favored string formatting.
 | ||||||
| @ -380,7 +363,6 @@ enum py_PredefinedTypes { | |||||||
|     tp_float, |     tp_float, | ||||||
|     tp_bool, |     tp_bool, | ||||||
|     tp_str, |     tp_str, | ||||||
|     tp_str_iterator, |  | ||||||
|     tp_list,   // c11_vector
 |     tp_list,   // c11_vector
 | ||||||
|     tp_tuple,  // N slots
 |     tp_tuple,  // N slots
 | ||||||
|     tp_slice,  // 3 slots (start, stop, step)
 |     tp_slice,  // 3 slots (start, stop, step)
 | ||||||
| @ -402,7 +384,7 @@ enum py_PredefinedTypes { | |||||||
|     tp_not_implemented_type, |     tp_not_implemented_type, | ||||||
|     tp_ellipsis, |     tp_ellipsis, | ||||||
|     tp_syntax_error, |     tp_syntax_error, | ||||||
|     tp_stop_iteration, |     tp_stop_iteration | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
|  | |||||||
| @ -38,8 +38,8 @@ void c11_string__delete(c11_string* self) { free(self); } | |||||||
| 
 | 
 | ||||||
| c11_sv c11_string__sv(c11_string* self) { return (c11_sv){self->data, self->size}; } | c11_sv c11_string__sv(c11_string* self) { return (c11_sv){self->data, self->size}; } | ||||||
| 
 | 
 | ||||||
| c11_string* c11_sv__replace(c11_sv self, char old, char new_) { | c11_string* c11_string__replace(c11_string* self, char old, char new_) { | ||||||
|     c11_string* retval = c11_string__new2(self.data, self.size); |     c11_string* retval = c11_string__copy(self); | ||||||
|     char* p = (char*)retval->data; |     char* p = (char*)retval->data; | ||||||
|     for(int i = 0; i < retval->size; i++) { |     for(int i = 0; i < retval->size; i++) { | ||||||
|         if(p[i] == old) p[i] = new_; |         if(p[i] == old) p[i] = new_; | ||||||
| @ -47,37 +47,22 @@ c11_string* c11_sv__replace(c11_sv self, char old, char new_) { | |||||||
|     return retval; |     return retval; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| c11_string* c11_sv__replace2(c11_sv self, c11_sv old, c11_sv new_) { | int c11_string__u8_length(c11_string* self) { | ||||||
|     c11_sbuf buf; |     return c11__byte_index_to_unicode(self->data, self->size); | ||||||
|     c11_sbuf__ctor(&buf); |  | ||||||
|     int start = 0; |  | ||||||
|     while(true) { |  | ||||||
|         int i = c11_sv__index2(self, old, start); |  | ||||||
|         if(i == -1) break; |  | ||||||
|         c11_sv tmp = c11_sv__slice2(self, start, i); |  | ||||||
|         c11_sbuf__write_sv(&buf, tmp); |  | ||||||
|         c11_sbuf__write_sv(&buf, new_); |  | ||||||
|         start = i + old.size; |  | ||||||
|     } |  | ||||||
|     c11_sv tmp = c11_sv__slice2(self, start, self.size); |  | ||||||
|     c11_sbuf__write_sv(&buf, tmp); |  | ||||||
|     return c11_sbuf__submit(&buf); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int c11_sv__u8_length(c11_sv sv) { return c11__byte_index_to_unicode(sv.data, sv.size); } | c11_sv c11_string__u8_getitem(c11_string* self, int i) { | ||||||
| 
 |     i = c11__unicode_index_to_byte(self->data, i); | ||||||
| c11_sv c11_sv__u8_getitem(c11_sv sv, int i) { |     int size = c11__u8_header(self->data[i], false); | ||||||
|     i = c11__unicode_index_to_byte(sv.data, i); |     return c11_sv__slice2(c11_string__sv(self), i, i + size); | ||||||
|     int size = c11__u8_header(sv.data[i], false); |  | ||||||
|     return c11_sv__slice2(sv, i, i + size); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| c11_string* c11_sv__u8_slice(c11_sv sv, int start, int stop, int step) { | c11_string* c11_string__u8_slice(c11_string* self, int start, int stop, int step) { | ||||||
|     c11_sbuf ss; |     c11_sbuf ss; | ||||||
|     c11_sbuf__ctor(&ss); |     c11_sbuf__ctor(&ss); | ||||||
|     assert(step != 0); |     assert(step != 0); | ||||||
|     for(int i = start; step > 0 ? i < stop : i > stop; i += step) { |     for(int i = start; step > 0 ? i < stop : i > stop; i += step) { | ||||||
|         c11_sv unicode = c11_sv__u8_getitem(sv, i); |         c11_sv unicode = c11_string__u8_getitem(self, i); | ||||||
|         c11_sbuf__write_sv(&ss, unicode); |         c11_sbuf__write_sv(&ss, unicode); | ||||||
|     } |     } | ||||||
|     return c11_sbuf__submit(&ss); |     return c11_sbuf__submit(&ss); | ||||||
| @ -93,28 +78,20 @@ c11_sv c11_sv__slice2(c11_sv sv, int start, int stop) { | |||||||
|     return (c11_sv){sv.data + start, stop - start}; |     return (c11_sv){sv.data + start, stop - start}; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| c11_sv c11_sv__strip(c11_sv sv, c11_sv chars, bool left, bool right) { | c11_sv c11_sv__strip(c11_sv sv, bool left, bool right) { | ||||||
|     int L = 0; |     int L = 0; | ||||||
|     int R = c11_sv__u8_length(sv); |     int R = sv.size; | ||||||
|  |     const char* data = sv.data; | ||||||
|     if(left) { |     if(left) { | ||||||
|         while(L < R) { |         while(L < R && (data[L] == ' ' || data[L] == '\t' || data[L] == '\n' || data[L] == '\r')) | ||||||
|             c11_sv tmp = c11_sv__u8_getitem(sv, L); |  | ||||||
|             bool found = c11_sv__index2(chars, tmp, 0) != -1; |  | ||||||
|             if(!found) break; |  | ||||||
|             L++; |             L++; | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|     if(right) { |     if(right) { | ||||||
|         while(L < R) { |         while(L < R && (data[R - 1] == ' ' || data[R - 1] == '\t' || data[R - 1] == '\n' || | ||||||
|             c11_sv tmp = c11_sv__u8_getitem(sv, R - 1); |                         data[R - 1] == '\r')) | ||||||
|             bool found = c11_sv__index2(chars, tmp, 0) != -1; |  | ||||||
|             if(!found) break; |  | ||||||
|             R--; |             R--; | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|     int start = c11__unicode_index_to_byte(sv.data, L); |     return c11_sv__slice2(sv, L, R); | ||||||
|     int stop = c11__unicode_index_to_byte(sv.data, R); |  | ||||||
|     return c11_sv__slice2(sv, start, stop); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int c11_sv__index(c11_sv self, char c) { | int c11_sv__index(c11_sv self, char c) { | ||||||
|  | |||||||
| @ -753,7 +753,5 @@ bool py_binaryop(const py_Ref lhs, const py_Ref rhs, py_Name op, py_Name rop) { | |||||||
|     pk_VM* self = pk_current_vm; |     pk_VM* self = pk_current_vm; | ||||||
|     PUSH(lhs); |     PUSH(lhs); | ||||||
|     PUSH(rhs); |     PUSH(rhs); | ||||||
|     bool ok = stack_binaryop(self, op, rop); |     return stack_binaryop(self, op, rop); | ||||||
|     STACK_SHRINK(2); |  | ||||||
|     return ok; |  | ||||||
| } | } | ||||||
| @ -96,7 +96,6 @@ void pk_VM__ctor(pk_VM* self) { | |||||||
|     pk_number__register(); |     pk_number__register(); | ||||||
| 
 | 
 | ||||||
|     validate(tp_str, pk_str__register()); |     validate(tp_str, pk_str__register()); | ||||||
|     validate(tp_str_iterator, pk_str_iterator__register()); |  | ||||||
| 
 | 
 | ||||||
|     validate(tp_list, pk_list__register()); |     validate(tp_list, pk_list__register()); | ||||||
|     validate(tp_tuple, pk_VM__new_type(self, "tuple", tp_object, NULL, false)); |     validate(tp_tuple, pk_VM__new_type(self, "tuple", tp_object, NULL, false)); | ||||||
| @ -190,70 +189,6 @@ void pk_VM__pop_frame(pk_VM* self) { | |||||||
|     Frame__delete(frame); |     Frame__delete(frame); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void _clip_int(int* value, int min, int max) { |  | ||||||
|     if(*value < min) *value = min; |  | ||||||
|     if(*value > max) *value = max; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool pk__parse_int_slice(const py_Ref slice, int length, int* start, int* stop, int* step) { |  | ||||||
|     py_Ref s_start = py_getslot(slice, 0); |  | ||||||
|     py_Ref s_stop = py_getslot(slice, 1); |  | ||||||
|     py_Ref s_step = py_getslot(slice, 2); |  | ||||||
| 
 |  | ||||||
|     if(py_isnone(s_step)) |  | ||||||
|         *step = 1; |  | ||||||
|     else { |  | ||||||
|         if(!py_checkint(s_step)) return false; |  | ||||||
|         *step = py_toint(s_step); |  | ||||||
|     } |  | ||||||
|     if(*step == 0) return ValueError("slice step cannot be zero"); |  | ||||||
| 
 |  | ||||||
|     if(*step > 0) { |  | ||||||
|         if(py_isnone(s_start)) |  | ||||||
|             *start = 0; |  | ||||||
|         else { |  | ||||||
|             if(!py_checkint(s_start)) return false; |  | ||||||
|             *start = py_toint(s_start); |  | ||||||
|             if(*start < 0) *start += length; |  | ||||||
|             _clip_int(start, 0, length); |  | ||||||
|         } |  | ||||||
|         if(py_isnone(s_stop)) |  | ||||||
|             *stop = length; |  | ||||||
|         else { |  | ||||||
|             if(!py_checkint(s_stop)) return false; |  | ||||||
|             *stop = py_toint(s_stop); |  | ||||||
|             if(*stop < 0) *stop += length; |  | ||||||
|             _clip_int(stop, 0, length); |  | ||||||
|         } |  | ||||||
|     } else { |  | ||||||
|         if(py_isnone(s_start)) |  | ||||||
|             *start = length - 1; |  | ||||||
|         else { |  | ||||||
|             if(!py_checkint(s_start)) return false; |  | ||||||
|             *start = py_toint(s_start); |  | ||||||
|             if(*start < 0) *start += length; |  | ||||||
|             _clip_int(start, -1, length - 1); |  | ||||||
|         } |  | ||||||
|         if(py_isnone(s_stop)) |  | ||||||
|             *stop = -1; |  | ||||||
|         else { |  | ||||||
|             if(!py_checkint(s_stop)) return false; |  | ||||||
|             *stop = py_toint(s_stop); |  | ||||||
|             if(*stop < 0) *stop += length; |  | ||||||
|             _clip_int(stop, -1, length - 1); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool pk__normalize_index(int *index, int length){ |  | ||||||
|     if(*index < 0) *index += length; |  | ||||||
|     if(*index < 0 || *index >= length){ |  | ||||||
|         return IndexError("index out of range"); |  | ||||||
|     } |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| py_Type pk_VM__new_type(pk_VM* self, | py_Type pk_VM__new_type(pk_VM* self, | ||||||
|                         const char* name, |                         const char* name, | ||||||
|                         py_Type base, |                         py_Type base, | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ | |||||||
| 
 | 
 | ||||||
| typedef c11_vector List; | typedef c11_vector List; | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| void py_newlist(py_Ref out) { | void py_newlist(py_Ref out) { | ||||||
|     pk_VM* vm = pk_current_vm; |     pk_VM* vm = pk_current_vm; | ||||||
|     PyObject* obj = pk_ManagedHeap__gcnew(&vm->heap, tp_list, 0, sizeof(List)); |     PyObject* obj = pk_ManagedHeap__gcnew(&vm->heap, tp_list, 0, sizeof(List)); | ||||||
| @ -59,118 +60,13 @@ void py_list__insert(py_Ref self, int i, const py_Ref val) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////
 | ////////////////////////////////
 | ||||||
| static bool _py_list__len__(int argc, py_Ref argv) { | static bool _py_list__len__(int argc, py_Ref argv){ | ||||||
|     PY_CHECK_ARGC(1); |     PY_CHECK_ARGC(1); | ||||||
|     py_i64 res = py_list__len(py_arg(0)); |     py_i64 res = py_list__len(py_arg(0)); | ||||||
|     py_newint(py_retval(), res); |     py_newint(py_retval(), res); | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool _py_list__eq__(int argc, py_Ref argv) { |  | ||||||
|     PY_CHECK_ARGC(2); |  | ||||||
|     py_Ref _0 = py_arg(0); |  | ||||||
|     py_Ref _1 = py_arg(1); |  | ||||||
|     if(py_istype(_1, tp_list)) { |  | ||||||
|         int length = py_list__len(_0); |  | ||||||
|         if(length != py_list__len(_1)) { |  | ||||||
|             py_newbool(py_retval(), false); |  | ||||||
|             return true; |  | ||||||
|         } |  | ||||||
|         for(int i = 0; i < length; i++) { |  | ||||||
|             py_Ref a = py_list__getitem(_0, i); |  | ||||||
|             py_Ref b = py_list__getitem(_1, i); |  | ||||||
|             int res = py_eq(a, b); |  | ||||||
|             if(res == -1) return false; |  | ||||||
|             if(res == 0) { |  | ||||||
|                 py_newbool(py_retval(), false); |  | ||||||
|                 return true; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         py_newbool(py_retval(), true); |  | ||||||
|     } else { |  | ||||||
|         py_newnotimplemented(py_retval()); |  | ||||||
|     } |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool _py_list__ne__(int argc, py_Ref argv) { |  | ||||||
|     bool ok = _py_list__eq__(argc, argv); |  | ||||||
|     if(!ok) return false; |  | ||||||
|     py_Ref retval = py_retval(); |  | ||||||
|     py_newbool(retval, !py_tobool(retval)); |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool _py_list__new__(int argc, py_Ref argv) { |  | ||||||
|     if(argc == 1) { |  | ||||||
|         py_newlist(py_retval()); |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
|     if(argc == 2) { |  | ||||||
|         py_Ref iter = py_pushtmp(); |  | ||||||
|         py_Ref list = py_pushtmp(); |  | ||||||
|         if(!py_iter(py_arg(1))) return false; |  | ||||||
|         *iter = *py_retval(); |  | ||||||
|         py_newlist(list); |  | ||||||
|         while(true) { |  | ||||||
|             int res = py_next(iter); |  | ||||||
|             if(res == -1) return false; |  | ||||||
|             if(res) { |  | ||||||
|                 py_list__append(list, py_retval()); |  | ||||||
|             } else { |  | ||||||
|                 break; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         *py_retval() = *list; |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
|     return TypeError("list() takes at most 1 argument"); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool _py_list__getitem__(int argc, py_Ref argv) { |  | ||||||
|     PY_CHECK_ARGC(2); |  | ||||||
|     List* self = py_touserdata(py_arg(0)); |  | ||||||
|     py_Ref _1 = py_arg(1); |  | ||||||
|     if(_1->type == tp_int) { |  | ||||||
|         int index = py_toint(py_arg(1)); |  | ||||||
|         if(!pk__normalize_index(&index, self->count)) return false; |  | ||||||
|         *py_retval() = c11__getitem(py_TValue, self, index); |  | ||||||
|         return true; |  | ||||||
|     } else if(_1->type == tp_slice) { |  | ||||||
|         int start, stop, step; |  | ||||||
|         bool ok = pk__parse_int_slice(_1, self->count, &start, &stop, &step); |  | ||||||
|         if(!ok) return false; |  | ||||||
|         py_newlist(py_retval()); |  | ||||||
|         List* list = py_touserdata(py_retval()); |  | ||||||
|         PK_SLICE_LOOP(i, start, stop, step) { |  | ||||||
|             c11_vector__push(py_TValue, list, c11__getitem(py_TValue, self, i)); |  | ||||||
|         } |  | ||||||
|         return true; |  | ||||||
|     } else { |  | ||||||
|         return TypeError("list indices must be integers"); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool _py_list__setitem__(int argc, py_Ref argv) { |  | ||||||
|     PY_CHECK_ARGC(3); |  | ||||||
|     PY_CHECK_ARG_TYPE(1, tp_int); |  | ||||||
|     List* self = py_touserdata(py_arg(0)); |  | ||||||
|     int index = py_toint(py_arg(1)); |  | ||||||
|     if(!pk__normalize_index(&index, self->count)) return false; |  | ||||||
|     c11__setitem(py_TValue, self, index, *py_arg(2)); |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool _py_list__delitem__(int argc, py_Ref argv) { |  | ||||||
|     PY_CHECK_ARGC(2); |  | ||||||
|     PY_CHECK_ARG_TYPE(1, tp_int); |  | ||||||
|     List* self = py_touserdata(py_arg(0)); |  | ||||||
|     int index = py_toint(py_arg(1)); |  | ||||||
|     if(!pk__normalize_index(&index, self->count)) return false; |  | ||||||
|     c11_vector__erase(py_TValue, self, index); |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| py_Type pk_list__register() { | py_Type pk_list__register() { | ||||||
|     pk_VM* vm = pk_current_vm; |     pk_VM* vm = pk_current_vm; | ||||||
|     py_Type type = pk_VM__new_type(vm, "list", tp_object, NULL, false); |     py_Type type = pk_VM__new_type(vm, "list", tp_object, NULL, false); | ||||||
| @ -178,11 +74,5 @@ py_Type pk_list__register() { | |||||||
|     ti->dtor = (void (*)(void*))c11_vector__dtor; |     ti->dtor = (void (*)(void*))c11_vector__dtor; | ||||||
| 
 | 
 | ||||||
|     py_bindmagic(type, __len__, _py_list__len__); |     py_bindmagic(type, __len__, _py_list__len__); | ||||||
|     py_bindmagic(type, __eq__, _py_list__eq__); |  | ||||||
|     py_bindmagic(type, __ne__, _py_list__ne__); |  | ||||||
|     py_bindmagic(type, __new__, _py_list__new__); |  | ||||||
|     py_bindmagic(type, __getitem__, _py_list__getitem__); |  | ||||||
|     py_bindmagic(type, __setitem__, _py_list__setitem__); |  | ||||||
|     py_bindmagic(type, __delitem__, _py_list__delitem__); |  | ||||||
|     return type; |     return type; | ||||||
| } | } | ||||||
| @ -60,24 +60,6 @@ bool py_hash(const py_Ref val, int64_t* out) { | |||||||
|     return TypeError("unhashable type: '%t'", val->type); |     return TypeError("unhashable type: '%t'", val->type); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool py_iter(const py_Ref val) { |  | ||||||
|     py_Ref tmp = py_tpfindmagic(val->type, __iter__); |  | ||||||
|     if(!tmp) return TypeError("'%t' object is not iterable", val->type); |  | ||||||
|     return py_call(tmp, 1, val); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int py_next(const py_Ref val) { |  | ||||||
|     py_Ref tmp = py_tpfindmagic(val->type, __next__); |  | ||||||
|     if(!tmp) return TypeError("'%t' object is not an iterator", val->type); |  | ||||||
|     bool ok = py_call(tmp, 1, val); |  | ||||||
|     if(ok) { |  | ||||||
|         py_Ref retval = py_retval(); |  | ||||||
|         bool is_end = retval->type == tp_type && py_totype(retval) == tp_stop_iteration; |  | ||||||
|         return !is_end; |  | ||||||
|     } |  | ||||||
|     return -1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int py_getattr(const py_Ref self, py_Name name, py_Ref out) { return -1; } | int py_getattr(const py_Ref self, py_Name name, py_Ref out) { return -1; } | ||||||
| 
 | 
 | ||||||
| bool py_setattr(py_Ref self, py_Name name, const py_Ref val) { return false; } | bool py_setattr(py_Ref self, py_Name name, const py_Ref val) { return false; } | ||||||
|  | |||||||
| @ -158,30 +158,17 @@ static bool _py_str__repr__(int argc, py_Ref argv) { | |||||||
| 
 | 
 | ||||||
| static bool _py_str__iter__(int argc, py_Ref argv) { | static bool _py_str__iter__(int argc, py_Ref argv) { | ||||||
|     PY_CHECK_ARGC(1); |     PY_CHECK_ARGC(1); | ||||||
|     return py_tpcall(tp_str_iterator, 1, argv); |     assert(false); | ||||||
|  |     return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool _py_str__getitem__(int argc, py_Ref argv) { | static bool _py_str__getitem__(int argc, py_Ref argv) { | ||||||
|     PY_CHECK_ARGC(2); |     PY_CHECK_ARGC(2); | ||||||
|     c11_sv self = c11_string__sv(py_touserdata(&argv[0])); |     c11_string* self = py_touserdata(&argv[0]); | ||||||
|     py_Ref _1 = py_arg(1); |     PY_CHECK_ARG_TYPE(1, tp_int); | ||||||
|     if(_1->type == tp_int) { |     c11_sv res = c11_string__u8_getitem(self, py_toint(py_arg(1))); | ||||||
|         int index = py_toint(py_arg(1)); |     py_newstrn(py_retval(), res.data, res.size); | ||||||
|         if(!pk__normalize_index(&index, self.size)) return false; |     return true; | ||||||
|         c11_sv res = c11_sv__u8_getitem(self, index); |  | ||||||
|         py_newstrn(py_retval(), res.data, res.size); |  | ||||||
|         return true; |  | ||||||
|     } else if(_1->type == tp_slice) { |  | ||||||
|         int start, stop, step; |  | ||||||
|         bool ok = pk__parse_int_slice(_1, c11_sv__u8_length(self), &start, &stop, &step); |  | ||||||
|         if(!ok) return false; |  | ||||||
|         c11_string* res = c11_sv__u8_slice(self, start, stop, step); |  | ||||||
|         py_newstrn(py_retval(), res->data, res->size); |  | ||||||
|         c11_string__delete(res); |  | ||||||
|         return true; |  | ||||||
|     } else { |  | ||||||
|         return TypeError("string indices must be integers"); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #define DEF_STR_CMP_OP(op, __f, __cond)                                                            \ | #define DEF_STR_CMP_OP(op, __f, __cond)                                                            \ | ||||||
| @ -260,202 +247,14 @@ static bool _py_str__endswith(int argc, py_Ref argv) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool _py_str__join(int argc, py_Ref argv) { | static bool _py_str__join(int argc, py_Ref argv) { | ||||||
|     PY_CHECK_ARGC(2); |     assert(false); | ||||||
|     c11_sv self = c11_string__sv(py_touserdata(&argv[0])); |     // PY_CHECK_ARGC(2);
 | ||||||
|     py_Ref _1 = py_arg(1); |     // c11_sbuf buf;
 | ||||||
|     // join a list or tuple
 |     // c11_sbuf__ctor(&buf);
 | ||||||
|     py_TValue* p; |     // c11_string* sep = py_touserdata(&argv[0]);
 | ||||||
|     int length; |     // py_Ref iter = py_pushtmp();
 | ||||||
|     if(py_istype(_1, tp_list)) { |     // py_iter(iter, &argv[1]);
 | ||||||
|         p = py_list__getitem(_1, 0); |     return false; | ||||||
|         length = py_list__len(_1); |  | ||||||
|     } else if(py_istype(_1, tp_tuple)) { |  | ||||||
|         p = py_tuple__getitem(_1, 0); |  | ||||||
|         length = py_tuple__len(_1); |  | ||||||
|     } else { |  | ||||||
|         return TypeError("join() argument must be a list or tuple"); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     c11_sbuf buf; |  | ||||||
|     c11_sbuf__ctor(&buf); |  | ||||||
|     for(int i = 0; i < length; i++) { |  | ||||||
|         if(i > 0) c11_sbuf__write_sv(&buf, self); |  | ||||||
|         if(!py_checkstr(&p[i])) { |  | ||||||
|             c11_sbuf__dtor(&buf); |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
|         c11_string* item = py_touserdata(&p[i]); |  | ||||||
|         c11_sbuf__write_cstrn(&buf, item->data, item->size); |  | ||||||
|     } |  | ||||||
|     c11_string* res = c11_sbuf__submit(&buf); |  | ||||||
|     py_newstrn(py_retval(), res->data, res->size); |  | ||||||
|     c11_string__delete(res); |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool _py_str__replace(int argc, py_Ref argv) { |  | ||||||
|     PY_CHECK_ARGC(3); |  | ||||||
|     c11_string* self = py_touserdata(&argv[0]); |  | ||||||
|     PY_CHECK_ARG_TYPE(1, tp_str); |  | ||||||
|     PY_CHECK_ARG_TYPE(2, tp_str); |  | ||||||
|     c11_string* old = py_touserdata(&argv[1]); |  | ||||||
|     c11_string* new_ = py_touserdata(&argv[2]); |  | ||||||
|     c11_string* res = |  | ||||||
|         c11_sv__replace2(c11_string__sv(self), c11_string__sv(old), c11_string__sv(new_)); |  | ||||||
|     py_newstrn(py_retval(), res->data, res->size); |  | ||||||
|     c11_string__delete(res); |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool _py_str__split(int argc, py_Ref argv) { |  | ||||||
|     c11_sv self = c11_string__sv(py_touserdata(&argv[0])); |  | ||||||
|     c11_vector res; |  | ||||||
|     if(argc > 2) return TypeError("split() takes at most 2 arguments"); |  | ||||||
|     if(argc == 1) { |  | ||||||
|         // sep = ' '
 |  | ||||||
|         res = c11_sv__split(self, ' '); |  | ||||||
|     } |  | ||||||
|     if(argc == 2) { |  | ||||||
|         // sep = argv[1]
 |  | ||||||
|         if(!py_checkstr(&argv[1])) return false; |  | ||||||
|         c11_sv sep = c11_string__sv(py_touserdata(&argv[1])); |  | ||||||
|         res = c11_sv__split2(self, sep); |  | ||||||
|     } |  | ||||||
|     py_newlistn(py_retval(), res.count); |  | ||||||
|     for(int i = 0; i < res.count; i++) { |  | ||||||
|         c11_sv item = c11__getitem(c11_sv, &res, i); |  | ||||||
|         py_newstrn(py_list__getitem(py_retval(), i), item.data, item.size); |  | ||||||
|     } |  | ||||||
|     c11_vector__dtor(&res); |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool _py_str__count(int argc, py_Ref argv) { |  | ||||||
|     PY_CHECK_ARGC(2); |  | ||||||
|     c11_string* self = py_touserdata(&argv[0]); |  | ||||||
|     PY_CHECK_ARG_TYPE(1, tp_str); |  | ||||||
|     c11_string* sub = py_touserdata(&argv[1]); |  | ||||||
|     int res = c11_sv__count(c11_string__sv(self), c11_string__sv(sub)); |  | ||||||
|     py_newint(py_retval(), res); |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool _py_str__strip_impl(bool left, bool right, int argc, py_Ref argv) { |  | ||||||
|     c11_sv self = c11_string__sv(py_touserdata(&argv[0])); |  | ||||||
|     c11_sv chars; |  | ||||||
|     if(argc == 1) { |  | ||||||
|         chars = (c11_sv){" \t\n\r", 4}; |  | ||||||
|     } else if(argc == 2) { |  | ||||||
|         if(!py_checkstr(&argv[1])) return false; |  | ||||||
|         chars = c11_string__sv(py_touserdata(&argv[1])); |  | ||||||
|     } else { |  | ||||||
|         return TypeError("strip() takes at most 2 arguments"); |  | ||||||
|     } |  | ||||||
|     c11_sv res = c11_sv__strip(self, chars, left, right); |  | ||||||
|     py_newstrn(py_retval(), res.data, res.size); |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool _py_str__strip(int argc, py_Ref argv) { |  | ||||||
|     return _py_str__strip_impl(true, true, argc, argv); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool _py_str__lstrip(int argc, py_Ref argv) { |  | ||||||
|     return _py_str__strip_impl(true, false, argc, argv); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool _py_str__rstrip(int argc, py_Ref argv) { |  | ||||||
|     return _py_str__strip_impl(false, true, argc, argv); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool _py_str__zfill(int argc, py_Ref argv) { |  | ||||||
|     PY_CHECK_ARGC(2); |  | ||||||
|     c11_sv self = c11_string__sv(py_touserdata(&argv[0])); |  | ||||||
|     PY_CHECK_ARG_TYPE(1, tp_int); |  | ||||||
|     int width = py_toint(py_arg(1)); |  | ||||||
|     int delta = width - c11_sv__u8_length(self); |  | ||||||
|     if(delta <= 0) { |  | ||||||
|         *py_retval() = argv[0]; |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
|     c11_sbuf buf; |  | ||||||
|     c11_sbuf__ctor(&buf); |  | ||||||
|     for(int i = 0; i < delta; i++) { |  | ||||||
|         c11_sbuf__write_char(&buf, '0'); |  | ||||||
|     } |  | ||||||
|     c11_sbuf__write_sv(&buf, self); |  | ||||||
|     c11_string* res = c11_sbuf__submit(&buf); |  | ||||||
|     py_newstrn(py_retval(), res->data, res->size); |  | ||||||
|     c11_string__delete(res); |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool _py_str__widthjust_impl(bool left, int argc, py_Ref argv) { |  | ||||||
|     if(argc > 1 + 2) return TypeError("expected at most 2 arguments"); |  | ||||||
|     char pad; |  | ||||||
|     if(argc == 1 + 1) { |  | ||||||
|         pad = ' '; |  | ||||||
|     } else { |  | ||||||
|         if(!py_checkstr(&argv[2])) return false; |  | ||||||
|         c11_string* padstr = py_touserdata(&argv[2]); |  | ||||||
|         if(padstr->size != 1) |  | ||||||
|             return TypeError("The fill character must be exactly one character long"); |  | ||||||
|         pad = padstr->data[0]; |  | ||||||
|     } |  | ||||||
|     c11_sv self = c11_string__sv(py_touserdata(&argv[0])); |  | ||||||
|     PY_CHECK_ARG_TYPE(1, tp_int); |  | ||||||
|     int width = py_toint(py_arg(1)); |  | ||||||
|     if(width <= self.size) { |  | ||||||
|         *py_retval() = argv[0]; |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
|     c11_sbuf buf; |  | ||||||
|     c11_sbuf__ctor(&buf); |  | ||||||
|     if(left) { |  | ||||||
|         c11_sbuf__write_sv(&buf, self); |  | ||||||
|         for(int i = 0; i < width - self.size; i++) { |  | ||||||
|             c11_sbuf__write_char(&buf, pad); |  | ||||||
|         } |  | ||||||
|     } else { |  | ||||||
|         for(int i = 0; i < width - self.size; i++) { |  | ||||||
|             c11_sbuf__write_char(&buf, pad); |  | ||||||
|         } |  | ||||||
|         c11_sbuf__write_sv(&buf, self); |  | ||||||
|     } |  | ||||||
|     c11_string* res = c11_sbuf__submit(&buf); |  | ||||||
|     py_newstrn(py_retval(), res->data, res->size); |  | ||||||
|     c11_string__delete(res); |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool _py_str__ljust(int argc, py_Ref argv) { |  | ||||||
|     return _py_str__widthjust_impl(true, argc, argv); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool _py_str__rjust(int argc, py_Ref argv) { |  | ||||||
|     return _py_str__widthjust_impl(false, argc, argv); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool _py_str__find(int argc, py_Ref argv) { |  | ||||||
|     if(argc > 3) return TypeError("find() takes at most 3 arguments"); |  | ||||||
|     int start = 0; |  | ||||||
|     if(argc == 3) { |  | ||||||
|         PY_CHECK_ARG_TYPE(2, tp_int); |  | ||||||
|         start = py_toint(py_arg(2)); |  | ||||||
|     } |  | ||||||
|     c11_string* self = py_touserdata(&argv[0]); |  | ||||||
|     PY_CHECK_ARG_TYPE(1, tp_str); |  | ||||||
|     c11_string* sub = py_touserdata(&argv[1]); |  | ||||||
|     int res = c11_sv__index2(c11_string__sv(self), c11_string__sv(sub), start); |  | ||||||
|     py_newint(py_retval(), res); |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool _py_str__index(int argc, py_Ref argv) { |  | ||||||
|     bool ok = _py_str__find(argc, argv); |  | ||||||
|     if(!ok) return false; |  | ||||||
|     if(py_toint(py_retval()) == -1) return ValueError("substring not found"); |  | ||||||
|     return true; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| py_Type pk_str__register() { | py_Type pk_str__register() { | ||||||
| @ -487,57 +286,6 @@ py_Type pk_str__register() { | |||||||
|     py_bindmethod(tp_str, "startswith", _py_str__startswith); |     py_bindmethod(tp_str, "startswith", _py_str__startswith); | ||||||
|     py_bindmethod(tp_str, "endswith", _py_str__endswith); |     py_bindmethod(tp_str, "endswith", _py_str__endswith); | ||||||
|     py_bindmethod(tp_str, "join", _py_str__join); |     py_bindmethod(tp_str, "join", _py_str__join); | ||||||
|     py_bindmethod(tp_str, "replace", _py_str__replace); |  | ||||||
|     py_bindmethod(tp_str, "split", _py_str__split); |  | ||||||
|     py_bindmethod(tp_str, "count", _py_str__count); |  | ||||||
|     py_bindmethod(tp_str, "strip", _py_str__strip); |  | ||||||
|     py_bindmethod(tp_str, "lstrip", _py_str__lstrip); |  | ||||||
|     py_bindmethod(tp_str, "rstrip", _py_str__rstrip); |  | ||||||
|     py_bindmethod(tp_str, "zfill", _py_str__zfill); |  | ||||||
|     py_bindmethod(tp_str, "ljust", _py_str__ljust); |  | ||||||
|     py_bindmethod(tp_str, "rjust", _py_str__rjust); |  | ||||||
|     py_bindmethod(tp_str, "find", _py_str__find); |  | ||||||
|     py_bindmethod(tp_str, "index", _py_str__index); |  | ||||||
|     return type; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool _py_str_iterator__new__(int argc, py_Ref argv) { |  | ||||||
|     PY_CHECK_ARGC(2); |  | ||||||
|     PY_CHECK_ARG_TYPE(1, tp_str); |  | ||||||
|     int* ud = py_newobject(py_retval(), tp_str_iterator, 1, sizeof(int)); |  | ||||||
|     *ud = 0; |  | ||||||
|     py_setslot(py_retval(), 0, &argv[1]); |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool _py_str_iterator__iter__(int argc, py_Ref argv) { |  | ||||||
|     PY_CHECK_ARGC(1); |  | ||||||
|     *py_retval() = argv[0]; |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool _py_str_iterator__next__(int argc, py_Ref argv) { |  | ||||||
|     PY_CHECK_ARGC(1); |  | ||||||
|     int* ud = py_touserdata(&argv[0]); |  | ||||||
|     int size; |  | ||||||
|     const char* data = py_tostrn(py_getslot(argv, 0), &size); |  | ||||||
|     if(*ud == size) { |  | ||||||
|         *py_retval() = pk_current_vm->StopIteration; |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
|     int start = *ud; |  | ||||||
|     int len = c11__u8_header(data[*ud], false); |  | ||||||
|     *ud += len; |  | ||||||
|     py_newstrn(py_retval(), data + start, len); |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| py_Type pk_str_iterator__register() { |  | ||||||
|     pk_VM* vm = pk_current_vm; |  | ||||||
|     py_Type type = pk_VM__new_type(vm, "str_iterator", tp_object, NULL, false); |  | ||||||
|     py_bindmagic(type, __new__, _py_str_iterator__new__); |  | ||||||
|     py_bindmagic(type, __iter__, _py_str_iterator__iter__); |  | ||||||
|     py_bindmagic(type, __next__, _py_str_iterator__next__); |  | ||||||
|     return type; |     return type; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -197,9 +197,7 @@ bool py_call(py_Ref f, int argc, py_Ref argv) { | |||||||
|         py_pushnil(); |         py_pushnil(); | ||||||
|         for(int i = 0; i < argc; i++) |         for(int i = 0; i < argc; i++) | ||||||
|             py_push(py_offset(argv, i)); |             py_push(py_offset(argv, i)); | ||||||
|         pk_FrameResult res = pk_VM__vectorcall(vm, argc, 0, false); |         return pk_VM__vectorcall(vm, argc, 0, false) == RES_ERROR; | ||||||
|         assert(res == RES_ERROR || res == RES_RETURN); |  | ||||||
|         return res == RES_RETURN; |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -294,10 +292,6 @@ const char* py_tpname(py_Type type) { | |||||||
|     return py_name2str(name); |     return py_name2str(name); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool py_tpcall(py_Type type, int argc, py_Ref argv){ |  | ||||||
|     return py_call(py_tpobject(type), argc, argv); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool py_callmagic(py_Name name, int argc, py_Ref argv) { | bool py_callmagic(py_Name name, int argc, py_Ref argv) { | ||||||
|     assert(argc >= 1); |     assert(argc >= 1); | ||||||
|     assert(py_ismagicname(name)); |     assert(py_ismagicname(name)); | ||||||
|  | |||||||
							
								
								
									
										107
									
								
								tests/04_str.py
									
									
									
									
									
								
							
							
						
						
									
										107
									
								
								tests/04_str.py
									
									
									
									
									
								
							| @ -101,6 +101,10 @@ assert s2.join( seq ) == "runoob" | |||||||
| assert 'x'.zfill(5) == '0000x' | assert 'x'.zfill(5) == '0000x' | ||||||
| assert '568'.zfill(1) == '568' | assert '568'.zfill(1) == '568' | ||||||
| 
 | 
 | ||||||
|  | def test(*seq): | ||||||
|  |     return s1.join(seq) | ||||||
|  | assert test("r", "u", "n", "o", "o", "b") == "r-u-n-o-o-b" | ||||||
|  | 
 | ||||||
| num = 6 | num = 6 | ||||||
| assert str(num) == '6' | assert str(num) == '6' | ||||||
| 
 | 
 | ||||||
| @ -108,6 +112,55 @@ assert str(num) == '6' | |||||||
| 测试 = "test" | 测试 = "test" | ||||||
| assert 测试 == "test" | assert 测试 == "test" | ||||||
| 
 | 
 | ||||||
|  | # 3rd slice | ||||||
|  | a = "Hello, World!" | ||||||
|  | assert a[::-1] == "!dlroW ,olleH" | ||||||
|  | assert a[::2] == "Hlo ol!" | ||||||
|  | assert a[2:5:2] == "lo" | ||||||
|  | assert a[5:2:-1] == ",ol" | ||||||
|  | assert a[5:2:-2] == ",l" | ||||||
|  | 
 | ||||||
|  | b = list(a) | ||||||
|  | assert b == ['H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!'] | ||||||
|  | assert b[::-1] == ['!', 'd', 'l', 'r', 'o', 'W', ' ', ',', 'o', 'l', 'l', 'e', 'H'] | ||||||
|  | assert b[::2] == ['H', 'l', 'o', ' ', 'o', 'l', '!'] | ||||||
|  | assert b[2:5:2] == ['l', 'o'] | ||||||
|  | assert b[5:2:-1] == [',', 'o', 'l'] | ||||||
|  | assert b[5:2:-2] == [',', 'l'] | ||||||
|  | 
 | ||||||
|  | a = '123' | ||||||
|  | assert a.rjust(5) == '  123' | ||||||
|  | assert a.rjust(5, '0') == '00123' | ||||||
|  | assert a.ljust(5) == '123  ' | ||||||
|  | assert a.ljust(5, '0') == '12300' | ||||||
|  | 
 | ||||||
|  | assert '\x30\x31\x32' == '012' | ||||||
|  | assert '\b\b\b' == '\x08\x08\x08' | ||||||
|  | assert repr('\x1f\x1e\x1f') == '\'\\x1f\\x1e\\x1f\'' | ||||||
|  | 
 | ||||||
|  | assert hex(-42) == '-0x2a' | ||||||
|  | assert hex(42) == '0x2a' | ||||||
|  | 
 | ||||||
|  | assert hex(0) == '0x0' | ||||||
|  | assert hex(1) == '0x1' | ||||||
|  | assert hex(15) == '0xf' | ||||||
|  | assert hex(16) == '0x10' | ||||||
|  | assert hex(255) == '0xff' | ||||||
|  | assert hex(256) == '0x100' | ||||||
|  | assert hex(257) == '0x101' | ||||||
|  | assert hex(17) == '0x11' | ||||||
|  | 
 | ||||||
|  | a = '123' | ||||||
|  | assert a.index('2') == 1 | ||||||
|  | assert a.index('1') == 0 | ||||||
|  | assert a.index('3') == 2 | ||||||
|  | 
 | ||||||
|  | assert a.index('2', 1) == 1 | ||||||
|  | assert a.index('1', 0) == 0 | ||||||
|  | 
 | ||||||
|  | assert a.find('1') == 0 | ||||||
|  | assert a.find('1', 1) == -1 | ||||||
|  | 
 | ||||||
| a = 'abcd' | a = 'abcd' | ||||||
| assert list(a) == ['a', 'b', 'c', 'd'] | assert list(a) == ['a', 'b', 'c', 'd'] | ||||||
| a = '测试' | a = '测试' | ||||||
| @ -125,60 +178,6 @@ assert list(a) == ['b'] | |||||||
| a = '测' | a = '测' | ||||||
| assert list(a) == ['测'] | assert list(a) == ['测'] | ||||||
| 
 | 
 | ||||||
| # 3rd slice |  | ||||||
| a = "Hello, World!" |  | ||||||
| assert a[::-1] == "!dlroW ,olleH" |  | ||||||
| assert a[::2] == "Hlo ol!" |  | ||||||
| assert a[2:5:2] == "lo" |  | ||||||
| assert a[5:2:-1] == ",ol" |  | ||||||
| assert a[5:2:-2] == ",l" |  | ||||||
| 
 |  | ||||||
| a = '123' |  | ||||||
| assert a.rjust(5) == '  123' |  | ||||||
| assert a.rjust(5, '0') == '00123' |  | ||||||
| assert a.ljust(5) == '123  ' |  | ||||||
| assert a.ljust(5, '0') == '12300' |  | ||||||
| 
 |  | ||||||
| assert '\x30\x31\x32' == '012' |  | ||||||
| assert '\b\b\b' == '\x08\x08\x08' |  | ||||||
| assert repr('\x1f\x1e\x1f') == '\'\\x1f\\x1e\\x1f\'' |  | ||||||
| 
 |  | ||||||
| a = '123' |  | ||||||
| assert a.index('2') == 1 |  | ||||||
| assert a.index('1') == 0 |  | ||||||
| assert a.index('3') == 2 |  | ||||||
| assert a.index('23') == 1 |  | ||||||
| 
 |  | ||||||
| assert a.index('2', 1) == 1 |  | ||||||
| assert a.index('1', 0) == 0 |  | ||||||
| 
 |  | ||||||
| assert a.find('1') == 0 |  | ||||||
| assert a.find('1', 1) == -1 |  | ||||||
| 
 |  | ||||||
| b = list("Hello, World!") |  | ||||||
| assert b == ['H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!'] |  | ||||||
| assert b[::-1] == ['!', 'd', 'l', 'r', 'o', 'W', ' ', ',', 'o', 'l', 'l', 'e', 'H'] |  | ||||||
| assert b[::2] == ['H', 'l', 'o', ' ', 'o', 'l', '!'] |  | ||||||
| assert b[2:5:2] == ['l', 'o'] |  | ||||||
| assert b[5:2:-1] == [',', 'o', 'l'] |  | ||||||
| assert b[5:2:-2] == [',', 'l'] |  | ||||||
| 
 |  | ||||||
| assert hex(-42) == '-0x2a' |  | ||||||
| assert hex(42) == '0x2a' |  | ||||||
| 
 |  | ||||||
| assert hex(0) == '0x0' |  | ||||||
| assert hex(1) == '0x1' |  | ||||||
| assert hex(15) == '0xf' |  | ||||||
| assert hex(16) == '0x10' |  | ||||||
| assert hex(255) == '0xff' |  | ||||||
| assert hex(256) == '0x100' |  | ||||||
| assert hex(257) == '0x101' |  | ||||||
| assert hex(17) == '0x11' |  | ||||||
| 
 |  | ||||||
| def test(*seq): |  | ||||||
|     return s1.join(seq) |  | ||||||
| assert test("r", "u", "n", "o", "o", "b") == "r-u-n-o-o-b" |  | ||||||
| 
 |  | ||||||
| # test format() | # test format() | ||||||
| assert "Hello, {}!".format("World") == "Hello, World!" | assert "Hello, {}!".format("World") == "Hello, World!" | ||||||
| assert "{} {} {}".format("I", "love", "Python") == "I love Python" | assert "{} {} {}".format("I", "love", "Python") == "I love Python" | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user