Compare commits

...

3 Commits

Author SHA1 Message Date
blueloveTH
104785c94b fix str.split 2024-11-14 19:52:23 +08:00
blueloveTH
630a5d04fc support vec* unpack 2024-11-14 19:16:27 +08:00
blueloveTH
212a705a4d add bindstaticmethod 2024-11-14 18:54:25 +08:00
13 changed files with 135 additions and 51 deletions

View File

@ -376,6 +376,11 @@ PK_API void py_bind(py_Ref obj, const char* sig, py_CFunction f);
/// @param name name of the method.
/// @param f function to bind.
PK_API void py_bindmethod(py_Type type, const char* name, py_CFunction f);
/// Bind a static method to type via "argc-based" style.
/// @param type the target type.
/// @param name name of the method.
/// @param f function to bind.
PK_API void py_bindstaticmethod(py_Type type, const char* name, py_CFunction f);
/// Bind a function to the object via "argc-based" style.
/// @param obj the target object.
/// @param name name of the function.

View File

@ -1,4 +1,4 @@
from typing import overload
from typing import overload, Iterator
class _vecF[T]:
ONE: T
@ -17,6 +17,9 @@ class _vecF[T]:
def length_squared(self) -> float: ...
def normalize(self) -> T: ...
# dummy iter for unpacking
def __iter__(self) -> Iterator[float]: ...
class _vecI[T]:
ONE: T
ZERO: T
@ -32,6 +35,9 @@ class _vecI[T]:
def dot(self, other: T) -> int: ...
# dummy iter for unpacking
def __iter__(self) -> Iterator[int]: ...
class vec2(_vecF['vec2']):
LEFT: vec2

View File

@ -30,6 +30,7 @@ LiteralString = _PLACEHOLDER
Iterable = _PLACEHOLDER
Generator = _PLACEHOLDER
Iterator = _PLACEHOLDER
Hashable = _PLACEHOLDER

File diff suppressed because one or more lines are too long

View File

@ -188,15 +188,13 @@ c11_vector /* T=c11_sv */ c11_sv__split(c11_sv self, char sep) {
int i = 0;
for(int j = 0; j < self.size; j++) {
if(data[j] == sep) {
if(j > i) {
c11_sv tmp = {data + i, j - i};
c11_vector__push(c11_sv, &retval, tmp);
}
assert(j >= i);
c11_sv tmp = {data + i, j - i};
c11_vector__push(c11_sv, &retval, tmp);
i = j + 1;
continue;
}
}
if(self.size > i) {
if(i <= self.size) {
c11_sv tmp = {data + i, self.size - i};
c11_vector__push(c11_sv, &retval, tmp);
}
@ -204,6 +202,7 @@ 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) {
if(sep.size == 1) return c11_sv__split(self, sep.data[0]);
c11_vector retval;
c11_vector__ctor(&retval, sizeof(c11_sv));
int start = 0;
@ -212,11 +211,11 @@ c11_vector /* T=c11_sv */ c11_sv__split2(c11_sv self, c11_sv sep) {
int i = c11_sv__index2(self, sep, start);
if(i == -1) break;
c11_sv tmp = {data + start, i - start};
if(tmp.size != 0) c11_vector__push(c11_sv, &retval, tmp);
c11_vector__push(c11_sv, &retval, tmp);
start = i + sep.size;
}
c11_sv tmp = {data + start, self.size - start};
if(tmp.size != 0) c11_vector__push(c11_sv, &retval, tmp);
c11_vector__push(c11_sv, &retval, tmp);
return retval;
}

View File

@ -8,7 +8,6 @@
#include "pocketpy/objects/error.h"
#include <stdbool.h>
static bool stack_unpack_sequence(VM* self, uint16_t arg);
static bool stack_format_object(VM* self, c11_sv spec);
#define CHECK_RETURN_FROM_EXCEPT_OR_FINALLY() \
@ -839,7 +838,71 @@ FrameResult VM__run_top_frame(VM* self) {
}
////////
case OP_UNPACK_SEQUENCE: {
if(!stack_unpack_sequence(self, byte.arg)) goto __ERROR;
py_TValue* p;
int length;
switch(TOP()->type) {
case tp_tuple: {
length = py_tuple_len(TOP());
p = py_tuple_data(TOP());
break;
}
case tp_list: {
length = py_list_len(TOP());
p = py_list_data(TOP());
break;
}
case tp_vec2i: {
length = 2;
if(byte.arg != length) break;
c11_vec2i val = py_tovec2i(TOP());
POP();
py_newint(SP()++, val.x);
py_newint(SP()++, val.y);
DISPATCH();
}
case tp_vec2: {
length = 2;
if(byte.arg != length) break;
c11_vec2 val = py_tovec2(TOP());
POP();
py_newfloat(SP()++, val.x);
py_newfloat(SP()++, val.y);
DISPATCH();
}
case tp_vec3i: {
length = 3;
if(byte.arg != length) break;
c11_vec3i val = py_tovec3i(TOP());
POP();
py_newint(SP()++, val.x);
py_newint(SP()++, val.y);
py_newint(SP()++, val.z);
DISPATCH();
}
case tp_vec3: {
length = 3;
if(byte.arg != length) break;
c11_vec3 val = py_tovec3(TOP());
POP();
py_newfloat(SP()++, val.x);
py_newfloat(SP()++, val.y);
py_newfloat(SP()++, val.z);
DISPATCH();
}
default: {
TypeError("expected list or tuple to unpack, got %t", TOP()->type);
goto __ERROR;
}
}
if(length != byte.arg) {
ValueError("expected %d values to unpack, got %d", byte.arg, length);
goto __ERROR;
}
POP();
for(int i = 0; i < length; i++) {
PUSH(p + i);
}
DISPATCH();
}
case OP_UNPACK_EX: {
@ -1141,18 +1204,6 @@ bool py_binaryop(py_Ref lhs, py_Ref rhs, py_Name op, py_Name rop) {
return ok;
}
static bool stack_unpack_sequence(VM* self, uint16_t arg) {
py_TValue* p;
int length = pk_arrayview(TOP(), &p);
if(length == -1) return TypeError("expected list or tuple to unpack, got %t", TOP()->type);
if(length != arg) return ValueError("expected %d values to unpack, got %d", arg, length);
POP();
for(int i = 0; i < length; i++) {
PUSH(p + i);
}
return true;
}
static bool stack_format_object(VM* self, c11_sv spec) {
// format TOS via `spec` inplace
// spec: '!r:.2f', '.2f'

View File

@ -860,8 +860,8 @@ void pk__add_module_linalg() {
py_newvec2(_const(vec2, "DOWN"), (c11_vec2){{0, 1}});
// clang-format on
py_bindmethod(vec2, "angle", vec2_angle_STATIC);
py_bindmethod(vec2, "smooth_damp", vec2_smoothdamp_STATIC);
py_bindstaticmethod(vec2, "angle", vec2_angle_STATIC);
py_bindstaticmethod(vec2, "smooth_damp", vec2_smoothdamp_STATIC);
py_bindproperty(vec2, "x", vec2__x, NULL);
py_bindproperty(vec2, "y", vec2__y, NULL);
@ -884,9 +884,9 @@ void pk__add_module_linalg() {
py_bindmethod(mat3x3, "inverse", mat3x3_inverse);
py_bindmethod(mat3x3, "copy_", mat3x3_copy_);
py_bindmethod(mat3x3, "inverse_", mat3x3_inverse_);
py_bindmethod(mat3x3, "zeros", mat3x3_zeros_STATIC);
py_bindmethod(mat3x3, "identity", mat3x3_identity_STATIC);
py_bindmethod(mat3x3, "trs", mat3x3_trs_STATIC);
py_bindstaticmethod(mat3x3, "zeros", mat3x3_zeros_STATIC);
py_bindstaticmethod(mat3x3, "identity", mat3x3_identity_STATIC);
py_bindstaticmethod(mat3x3, "trs", mat3x3_trs_STATIC);
py_bindmethod(mat3x3, "copy_trs_", mat3x3_copy_trs_);
py_bindmethod(mat3x3, "t", mat3x3_t);
py_bindmethod(mat3x3, "r", mat3x3_r);

View File

@ -1,9 +1,6 @@
#include "pocketpy/pocketpy.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/objects/object.h"
#include "pocketpy/interpreter/vm.h"
#include "pocketpy/common/sstream.h"
typedef struct array_iterator {
py_TValue* p;

View File

@ -117,7 +117,6 @@ static bool type__annotations__(int argc, py_Ref argv) {
}
void pk_object__register() {
// TODO: use staticmethod
py_bindmagic(tp_object, __new__, pk__object_new);
py_bindmagic(tp_object, __hash__, object__hash__);

View File

@ -317,21 +317,25 @@ static bool str_replace(int argc, py_Ref argv) {
static bool str_split(int argc, py_Ref argv) {
c11_sv self = c11_string__sv(py_touserdata(&argv[0]));
c11_vector res;
bool discard_empty = false;
if(argc > 2) return TypeError("split() takes at most 2 arguments");
if(argc == 1) {
// sep = ' '
// sep = None
res = c11_sv__split(self, ' ');
discard_empty = true;
}
if(argc == 2) {
// sep = argv[1]
if(!py_checkstr(&argv[1])) return false;
c11_sv sep = c11_string__sv(py_touserdata(&argv[1]));
if(sep.size == 0) return ValueError("empty separator");
res = c11_sv__split2(self, sep);
}
py_newlistn(py_retval(), res.length);
py_newlist(py_retval());
for(int i = 0; i < res.length; i++) {
c11_sv item = c11__getitem(c11_sv, &res, i);
py_newstrv(py_list_getitem(py_retval(), i), item);
c11_sv part = c11__getitem(c11_sv, &res, i);
if(discard_empty && part.size == 0) continue;
py_newstrv(py_list_emplace(py_retval()), part);
}
c11_vector__dtor(&res);
return true;

View File

@ -54,6 +54,17 @@ void py_bindmethod(py_Type type, const char* name, py_CFunction f) {
py_setdict(py_tpobject(type), py_name(name), &tmp);
}
void py_bindstaticmethod(py_Type type, const char* name, py_CFunction f) {
py_TValue tmp;
py_newnativefunc(&tmp, f);
bool ok = py_tpcall(tp_staticmethod, 1, &tmp);
if(!ok) {
py_printexc();
c11__abort("py_bindstaticmethod(): failed to create staticmethod");
}
py_setdict(py_tpobject(type), py_name(name), py_retval());
}
void py_bindfunc(py_Ref obj, const char* name, py_CFunction f) {
py_TValue tmp;
py_newnativefunc(&tmp, f);

View File

@ -9,7 +9,10 @@ assert 'testing5' >= 'test' + 'ing1'
assert 'abc' + 'def' == 'abcdef'
assert 'abc' * 3 == 'abcabcabc'
assert repr('\\\n\t\'\r\b\x48') == r"'\\\n\t\'\r\bH'"
assert repr('\\\n\t\'\r\b\x48') in [
r"'\\\n\t\'\r\bH'",
'"\\\\\\n\\t\'\\r\\x08H"',
]
a = ''
b = 'test'
@ -46,13 +49,19 @@ assert t.startswith('this') == True;
assert t.split('w') == ['this is string example....', 'o', '!!!']
assert "a,b,c".split(',') == ['a', 'b', 'c']
assert 'a,'.split(',') == ['a']
assert 'a,'.split(',') == ['a', '']
assert 'foo!!bar!!baz'.split('!!') == ['foo', 'bar', 'baz']
assert ' 4 3 '.split() == ['4', '3']
assert ' 4 3 '.split(' ') == ['4', '3']
assert ' 4 3 '.split(' ') == ['', '', '4', '3', '', '']
assert 'aa bb cccc'.split('cc') == ['aa bb ', '', '']
assert '.a.b.'.split('.') == ['', 'a', 'b', '']
assert '.a...b.'.split('.') == ['', 'a', '', '', 'b', '']
x = 'aa bb cccc'
assert x.split('cc') == ['aa bb ']
try:
'a'.split('')
exit(1)
except ValueError:
pass
assert '111'.count('1') == 3
assert '111'.count('11') == 1

View File

@ -315,16 +315,9 @@ val = vec2.angle(vec2(-1, 0), vec2(0, -1))
assert 1.57 < val < 1.58
# test about staticmethod
# class mymat3x3(mat3x3):
# def f(self):
# _0 = self.zeros()
# _1 = super().zeros()
# _2 = mat3x3.zeros()
# return _0 == _1 == _2
# assert mymat3x3().f()
d = mat3x3.identity()
d1 = mat3x3(1, 2, 3, 4, 5, 6, 7, 8, 9).identity()
assert d == d1
assert d.copy_(mat3x3.zeros()) is None
assert d == mat3x3.zeros()
@ -405,3 +398,12 @@ assert vec2(vec2i.LEFT) == vec2(-1, 0)
assert vec2(vec2i.RIGHT) == vec2(1, 0)
assert vec3(vec3i.ONE) == vec3(1, 1, 1)
assert vec3(vec3i.ZERO) == vec3(0, 0, 0)
x, y = vec2i(1, 2)
assert x == 1 and y == 2
x, y, z = vec3i(1, 2, 3)
assert x == 1 and y == 2 and z == 3
x, y = vec2(3.0, 4.0)
assert x == 3.0 and y == 4.0
x, y, z = vec3(1.0, 2.0, 3.0)
assert x == 1.0 and y == 2.0 and z == 3.0