support tuple(), '^', and more self-opt

This commit is contained in:
Lyon 2023-06-29 01:03:26 +08:00
parent 21155bfbb3
commit 129b2b95c8
16 changed files with 197 additions and 93 deletions

View File

@ -43,7 +43,7 @@ def list(*val) -> any: ...
def dict(*val) -> any: ...
def tuple(arg: any) -> any: ...
def tuple(*val) -> any: ...
def hex(val: int) -> str: ...

View File

@ -34,7 +34,7 @@
// "--gtest_filter=json.json_issue1"
// "--gtest_filter=json.err"
// "--gtest_filter=builtin.eval"
"--gtest_filter=stddata.pikafs_open_err"
// "--gtest_filter=stddata.pikafs_open_err"
],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",

View File

@ -43,7 +43,7 @@ def list(*val) -> any: ...
def dict(*val) -> any: ...
def tuple(arg: any) -> any: ...
def tuple(*val) -> any: ...
def hex(val: int) -> str: ...

View File

@ -91,7 +91,7 @@ Arg* json_encode_jsmn(jsmntok_t* t,
break;
}
case JSMN_OBJECT: {
PikaObj* ret = obj_newDict(NULL);
PikaObj* ret = objDict_new(NULL);
int num_keys = t[*index].size;
for (int i = 0; i < num_keys; i++) {
(*index)++;
@ -112,7 +112,7 @@ Arg* json_encode_jsmn(jsmntok_t* t,
break;
}
case JSMN_ARRAY: {
PikaObj* ret = obj_newList(NULL);
PikaObj* ret = objList_new(NULL);
jsmntok_t* key_tok = &t[*index];
int num_elements = key_tok->size;
for (int i = 0; i < num_elements; i++) {
@ -162,7 +162,7 @@ Arg* json_encode_cjson(cJSON* cjson) {
return arg_newStr(cjson->valuestring);
}
case pika_cJSON_Array: {
PikaObj* ret = obj_newList(NULL);
PikaObj* ret = objList_new(NULL);
for (int i = 0; i < pika_cJSON_GetArraySize(cjson); i++) {
cJSON* item = pika_cJSON_GetArrayItem(cjson, i);
Arg* nested_arg = json_encode_cjson(item);
@ -172,7 +172,7 @@ Arg* json_encode_cjson(cJSON* cjson) {
return arg_newObj(ret);
}
case pika_cJSON_Object: {
PikaObj* ret = obj_newDict(NULL);
PikaObj* ret = objDict_new(NULL);
cJSON* child = cjson->child;
for (int i = 0; i < pika_cJSON_GetArraySize(cjson); i++) {
char* key = child->string;

View File

@ -309,7 +309,7 @@ PikaObj* os_path_split(PikaObj* self, char* path) {
goto __exit; // 发生错误,跳转到 __exit 处做资源回收
}
tuple = obj_newTuple(arg_newStr(folder), arg_newStr(file));
tuple = objTuple_new(arg_newStr(folder), arg_newStr(file));
free(folder);
free(file);

View File

@ -47,15 +47,15 @@ Arg* _lua_val_to_arg(lua_State* L) {
PIKA_BOOL get_list = PIKA_FALSE;
PIKA_BOOL get_dict = PIKA_FALSE;
lua_pushnil(L); // push the first key
// PikaObj* dict = obj_newDict0();
// PikaObj* dict = objDict_new0();
while (lua_next(L, -2) != 0) {
// 'key' is at index -2 and 'value' at index -1
if (!get_list && !get_dict) {
if (lua_isinteger(L, -2)) {
ret = obj_newList(NULL);
ret = objList_new(NULL);
get_list = PIKA_TRUE;
} else {
ret = obj_newDict(NULL);
ret = objDict_new(NULL);
get_dict = PIKA_TRUE;
}
}

View File

@ -3172,8 +3172,13 @@ int builtins_len(PikaObj* self, Arg* arg) {
Arg* builtins_list(PikaObj* self, PikaTuple* val) {
#if PIKA_BUILTIN_STRUCT_ENABLE
if (1 == pikaTuple_getSize(val)) {
Arg* in = pikaTuple_getArg(val, 0);
obj_setArg(self, "__list", in);
Arg* aInput = pikaTuple_getArg(val, 0);
if (!arg_isIterable(aInput)) {
obj_setErrorCode(self, 1);
obj_setSysOut(self, "Error: input arg must be iterable");
return NULL;
}
obj_setArg(self, "__list", aInput);
/* clang-format off */
PIKA_PYTHON(
@res_list = []
@ -3204,8 +3209,7 @@ Arg* builtins_list(PikaObj* self, PikaTuple* val) {
};
return pikaVM_runByteCodeReturn(self, (uint8_t*)bytes, "@res_list");
}
PikaObj* New_PikaStdData_List(Args * args);
return arg_newDirectObj(New_PikaStdData_List);
return arg_newObj(objList_new(NULL));
#else
obj_setErrorCode(self, 1);
__platform_printf("[Error] built-in list is not enabled.\r\n");
@ -3224,11 +3228,15 @@ Arg* builtins_dict(PikaObj* self, PikaTuple* val) {
#endif
}
Arg* builtins_tuple(PikaObj* self, Arg* val) {
Arg* builtins_tuple(PikaObj* self, PikaTuple* val) {
#if PIKA_BUILTIN_STRUCT_ENABLE
obj_setErrorCode(self, 1);
__platform_printf("Error: tuple() is not supported.\r\n");
return arg_newNone();
Arg* tuple = builtins_list(self, val);
if (NULL == tuple) {
return NULL;
}
PikaObj* oTuple = arg_getObj(tuple);
oTuple->constructor = New_PikaStdData_Tuple;
return tuple;
#else
obj_setErrorCode(self, 1);
__platform_printf("[Error] built-in tuple is not enabled.\r\n");
@ -3745,8 +3753,7 @@ Arg* _max_min(PikaObj* self, PikaTuple* val, uint8_t* bc) {
}
if (size == 1) {
ArgType type = arg_getType(pikaTuple_getArg(val, 0));
if ((!argType_isObject(type) && (type != ARG_TYPE_STRING) &&
(type != ARG_TYPE_BYTES))) {
if (!argType_isIterable(type)) {
obj_setSysOut(self, "TypeError: object is not iterable");
obj_setErrorCode(self, PIKA_RES_ERR_INVALID_PARAM);
return NULL;
@ -3813,7 +3820,7 @@ Arg* builtins_bytearray___iter__(PikaObj* self) {
return arg_newRef(self);
}
int builtins_bytearray___len__(PikaObj* self){
int builtins_bytearray___len__(PikaObj* self) {
return obj_getBytesSize(self, "raw");
}

View File

@ -438,18 +438,18 @@ PikaObj* _pika_dict_new(int num_args, ...);
/* Macro to create a new tuple PikaObj with the given arguments (of type Arg*).
*/
#define obj_newTuple(...) \
#define objTuple_new(...) \
_pika_tuple_new(sizeof((Arg*[]){__VA_ARGS__}) / sizeof(Arg*), __VA_ARGS__)
/* Macro to create a new list PikaObj with the given arguments (of type Arg*).
*/
#define obj_newList(...) \
#define objList_new(...) \
_pika_list_new(sizeof((Arg*[]){__VA_ARGS__}) / sizeof(Arg*), __VA_ARGS__)
/* Macro to create a new dict PikaObj with the given arguments (of type Arg*).
*/
#define obj_newDict(...) \
#define objDict_new(...) \
_pika_dict_new(sizeof((Arg*[]){__VA_ARGS__, NULL}) / sizeof(Arg*) - 1, \
__VA_ARGS__)

View File

@ -623,7 +623,7 @@ char* Lexer_getTokenStream(Args* outBuffs, char* stmt) {
*/
if (('>' == c0) || ('<' == c0) || ('*' == c0) || ('/' == c0) ||
('+' == c0) || ('-' == c0) || ('!' == c0) || ('=' == c0) ||
('%' == c0)) {
('%' == c0) || ('^' == c0)) {
if ('=' == c1) {
char content[3] = {0};
content[0] = c0;
@ -825,10 +825,10 @@ static char* _solveEqualLevelOperator(Args* buffs,
}
static const char operators[][9] = {
"**", "~", "*", "/", "%", "//", "+", "-",
">>", "<<", "&", "^", "|", "<", "<=", ">",
">=", "!=", "==", " is ", " in ", "%=", "/=", "//=",
"-=", "+=", "*=", "**=", " not ", " and ", " or ", " import "};
"**", "~", "*", "/", "%", "//", "+", "-", ">>",
"<<", "&", "^", "|", "<", "<=", ">", ">=", "!=",
"==", " is ", " in ", "%=", "/=", "//=", "-=", "+=", "*=",
"**=", "^=", " not ", " and ", " or ", " import "};
char* Lexer_getOperator(Args* outBuffs, char* stmt) {
Args buffs = {0};
@ -1373,6 +1373,10 @@ char* Suger_format(Args* outBuffs, char* right) {
return res;
}
#define SELF_OPERATORES_LEN 4
static const char selfOperators[][SELF_OPERATORES_LEN] = {
"+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=", "<<=", ">>=", "**=", "//="};
uint8_t Suger_selfOperator(Args* outbuffs,
char* stmt,
char** right_p,
@ -1385,20 +1389,15 @@ uint8_t Suger_selfOperator(Args* outbuffs,
uint8_t is_left_exist = 0;
Args buffs = {0};
char _operator[2] = {0};
char _operator[3] = {0};
char* operator=(char*) _operator;
uint8_t is_right = 0;
if (Cursor_isContain(stmt, TOKEN_operator, "+=")) {
operator[0] = '+';
}
if (Cursor_isContain(stmt, TOKEN_operator, "-=")) {
operator[0] = '-';
}
if (Cursor_isContain(stmt, TOKEN_operator, "*=")) {
operator[0] = '*';
}
if (Cursor_isContain(stmt, TOKEN_operator, "/=")) {
operator[0] = '/';
for (uint8_t i = 0; i < sizeof(selfOperators) / SELF_OPERATORES_LEN; i++) {
if (Cursor_isContain(stmt, TOKEN_operator, (char*)selfOperators[i])) {
pika_platform_memcpy(operator, selfOperators[i],
strGetSize((char*)selfOperators[i]) - 1);
break;
}
}
/* not found self operator */
if (operator[0] == 0) {
@ -1408,12 +1407,12 @@ uint8_t Suger_selfOperator(Args* outbuffs,
is_left_exist = 1;
Cursor_forEach(cs, stmt) {
Cursor_iterStart(&cs);
if ((strEqu(cs.token1.pyload, "*=")) ||
(strEqu(cs.token1.pyload, "/=")) ||
(strEqu(cs.token1.pyload, "+=")) ||
(strEqu(cs.token1.pyload, "-="))) {
is_right = 1;
goto iter_continue;
for (uint8_t i = 0; i < sizeof(selfOperators) / SELF_OPERATORES_LEN;
i++) {
if (strEqu(cs.token1.pyload, (char*)selfOperators[i])) {
is_right = 1;
goto iter_continue;
}
}
if (!is_right) {
left_arg = arg_strAppend(left_arg, cs.token1.pyload);

View File

@ -2770,91 +2770,101 @@ static Arg* VM_instruction_handler_OPT(PikaObj* self,
switch (data[0]) {
case '+':
_OPT_ADD(&op);
goto exit;
goto __exit;
case '%':
if ((op.t1 == ARG_TYPE_INT) && (op.t2 == ARG_TYPE_INT)) {
op.res = arg_setInt(op.res, "", op.i1 % op.i2);
goto exit;
goto __exit;
}
#if PIKA_MATH_ENABLE
if (op.t1 == ARG_TYPE_FLOAT || op.t2 == ARG_TYPE_FLOAT) {
op.res = arg_setFloat(op.res, "", fmod(op.f1, op.f2));
goto exit;
goto __exit;
}
#endif
VMState_setErrorCode(vm, PIKA_RES_ERR_OPERATION_FAILED);
pika_platform_printf(
"TypeError: unsupported operand type(s) for %%: 'float'\n");
op.res = NULL;
goto exit;
goto __exit;
case '-':
_OPT_SUB(&op);
goto exit;
goto __exit;
}
if (data[1] == '=' && (data[0] == '!' || data[0] == '=')) {
_OPT_EQU(&op);
goto exit;
goto __exit;
}
if (data[1] == 0) {
switch (data[0]) {
case '<':
op.res = arg_setBool(op.res, "", op.f1 < op.f2);
goto exit;
goto __exit;
case '*':
if (op.num == 1) {
op.res = arg_copy(op.a2);
arg_setIsStarred(op.res, 1);
goto exit;
goto __exit;
}
if ((op.t1 == ARG_TYPE_FLOAT) || op.t2 == ARG_TYPE_FLOAT) {
op.res = arg_setFloat(op.res, "", op.f1 * op.f2);
goto exit;
goto __exit;
}
op.res = arg_setInt(op.res, "", op.i1 * op.i2);
goto exit;
goto __exit;
case '&':
if ((op.t1 == ARG_TYPE_INT) && (op.t2 == ARG_TYPE_INT)) {
op.res = arg_setInt(op.res, "", op.i1 & op.i2);
goto exit;
goto __exit;
}
VMState_setErrorCode(vm, PIKA_RES_ERR_OPERATION_FAILED);
pika_platform_printf(
"TypeError: unsupported operand type(s) for &: 'float'\n");
op.res = NULL;
goto exit;
goto __exit;
case '|':
if ((op.t1 == ARG_TYPE_INT) && (op.t2 == ARG_TYPE_INT)) {
op.res = arg_setInt(op.res, "", op.i1 | op.i2);
goto exit;
goto __exit;
}
VMState_setErrorCode(vm, PIKA_RES_ERR_OPERATION_FAILED);
pika_platform_printf(
"TypeError: unsupported operand type(s) for |: 'float'\n");
op.res = NULL;
goto exit;
goto __exit;
case '~':
if (op.t2 == ARG_TYPE_INT) {
op.res = arg_setInt(op.res, "", ~op.i2);
goto exit;
goto __exit;
}
VMState_setErrorCode(vm, PIKA_RES_ERR_OPERATION_FAILED);
pika_platform_printf(
"TypeError: unsupported operand type(s) for ~: 'float'\n");
op.res = NULL;
goto exit;
goto __exit;
case '/':
if (0 == op.f2) {
VMState_setErrorCode(vm, PIKA_RES_ERR_OPERATION_FAILED);
args_setSysOut(vm->locals->list,
"ZeroDivisionError: division by zero");
op.res = NULL;
goto exit;
goto __exit;
}
op.res = arg_setFloat(op.res, "", op.f1 / op.f2);
goto exit;
goto __exit;
case '>':
op.res = arg_setInt(op.res, "", op.f1 > op.f2);
goto exit;
goto __exit;
case '^':
if ((op.t1 == ARG_TYPE_INT) && (op.t2 == ARG_TYPE_INT)) {
op.res = arg_setInt(op.res, "", op.i1 ^ op.i2);
goto __exit;
}
VMState_setErrorCode(vm, PIKA_RES_ERR_OPERATION_FAILED);
pika_platform_printf(
"TypeError: unsupported operand type(s) for ^: 'float'\n");
op.res = NULL;
goto __exit;
}
}
if (data[1] == 'i' && data[2] == 'n') {
@ -2864,7 +2874,7 @@ static Arg* VM_instruction_handler_OPT(PikaObj* self,
} else {
op.res = arg_setBool(op.res, "", pika_false);
}
goto exit;
goto __exit;
}
#if !PIKA_NANO_ENABLE
if (argType_isObject(op.t2)) {
@ -2894,7 +2904,7 @@ static Arg* VM_instruction_handler_OPT(PikaObj* self,
pikaVM_runByteCode(obj2, (uint8_t*)bytes);
op.res =
arg_setBool(op.res, "", obj_getInt(obj2, "@res_contains"));
goto exit;
goto __exit;
}
}
#endif
@ -2904,22 +2914,29 @@ static Arg* VM_instruction_handler_OPT(PikaObj* self,
"Operation 'in' is not supported for this "
"type\n");
op.res = NULL;
goto exit;
goto __exit;
}
if (data[0] == '*' && data[1] == '*') {
_OPT_POW(&op);
goto exit;
goto __exit;
}
if (data[0] == '/' && data[1] == '/') {
if ((op.t1 == ARG_TYPE_INT) && (op.t2 == ARG_TYPE_INT)) {
op.res = arg_setInt(op.res, "", op.i1 / op.i2);
goto exit;
goto __exit;
}
#if PIKA_MATH_ENABLE
if ((op.t1 == ARG_TYPE_FLOAT) || (op.t2 == ARG_TYPE_FLOAT)) {
op.res = arg_setFloat(op.res, "", floor(op.f1 / op.f2));
goto __exit;
}
#endif
VMState_setErrorCode(vm, PIKA_RES_ERR_OPERATION_FAILED);
pika_platform_printf(
"TypeError: unsupported operand type(s) for //: 'float'\n");
"Operation float \\\\ float is not enabled, please set "
"PIKA_MATH_ENABLE\n");
op.res = NULL;
goto exit;
goto __exit;
}
if (data[1] == 'i' && data[2] == 's') {
#if !PIKA_NANO_ENABLE
@ -2929,70 +2946,72 @@ static Arg* VM_instruction_handler_OPT(PikaObj* self,
} else {
op.res = arg_setBool(op.res, "", pika_false);
}
goto exit;
goto __exit;
}
if ((op.t1 != op.t2) && (op.t1 != ARG_TYPE_NONE) &&
(op.t2 != ARG_TYPE_NONE)) {
op.res = arg_setInt(op.res, "", 0);
goto exit;
goto __exit;
}
#endif
op.opt = "==";
_OPT_EQU(&op);
goto exit;
goto __exit;
}
if (data[0] == '>' && data[1] == '=') {
op.res = arg_setBool(
op.res, "",
(op.f1 > op.f2) ||
((op.f1 - op.f2) * (op.f1 - op.f2) < (pika_float)0.000001));
goto exit;
goto __exit;
}
if (data[0] == '<' && data[1] == '=') {
op.res = arg_setBool(
op.res, "",
(op.f1 < op.f2) ||
((op.f1 - op.f2) * (op.f1 - op.f2) < (pika_float)0.000001));
goto exit;
goto __exit;
}
if (data[0] == '>' && data[1] == '>') {
if ((op.t1 == ARG_TYPE_INT) && (op.t2 == ARG_TYPE_INT)) {
op.res = arg_setInt(op.res, "", op.i1 >> op.i2);
goto exit;
goto __exit;
}
VMState_setErrorCode(vm, PIKA_RES_ERR_OPERATION_FAILED);
pika_platform_printf(
"TypeError: unsupported operand type(s) for >>: 'float'\n");
op.res = NULL;
goto exit;
goto __exit;
}
if (data[0] == '<' && data[1] == '<') {
if ((op.t1 == ARG_TYPE_INT) && (op.t2 == ARG_TYPE_INT)) {
op.res = arg_setInt(op.res, "", op.i1 << op.i2);
goto exit;
goto __exit;
}
VMState_setErrorCode(vm, PIKA_RES_ERR_OPERATION_FAILED);
pika_platform_printf(
"TypeError: unsupported operand type(s) for <<: 'float'\n");
op.res = NULL;
goto exit;
goto __exit;
}
if (data[0] == ' ' && data[1] == 'a' && data[2] == 'n' && data[3] == 'd' &&
data[4] == ' ') {
op.res = arg_setBool(op.res, "", op.i1 && op.i2);
goto exit;
goto __exit;
}
if (data[0] == ' ' && data[1] == 'o' && data[2] == 'r' && data[3] == ' ' &&
data[4] == 0) {
op.res = arg_setBool(op.res, "", op.i1 || op.i2);
goto exit;
goto __exit;
}
if (data[0] == ' ' && data[1] == 'n' && data[2] == 'o' && data[3] == 't' &&
data[4] == ' ' && data[5] == 0) {
op.res = arg_setBool(op.res, "", !op.i2);
goto exit;
goto __exit;
}
exit:
pika_platform_printf("Error: unknown operator '%s'\n", data);
VMState_setErrorCode(vm, PIKA_RES_ERR_OPERATION_FAILED);
__exit:
if (NULL != op.a1) {
arg_deinit(op.a1);
}

View File

@ -291,6 +291,11 @@ static inline uint8_t argType_isNative(ArgType type) {
(type) == ARG_TYPE_METHOD_NATIVE_CONSTRUCTOR);
}
static inline uint8_t argType_isIterable(ArgType type) {
return ((type) == ARG_TYPE_STRING || (type) == ARG_TYPE_BYTES ||
argType_isObject(type));
}
#define arg_isObject(__self) \
((__self != NULL) && (argType_isObject(arg_getType(__self))))
#define arg_isCallable(__self) \
@ -299,6 +304,8 @@ static inline uint8_t argType_isNative(ArgType type) {
((__self != NULL) && (argType_isConstructor(arg_getType(__self))))
#define arg_isNative(__self) \
((__self != NULL) && (argType_isNative(arg_getType(__self))))
#define arg_isIterable(__self) \
((__self != NULL) && (argType_isIterable(arg_getType(__self))))
#define arg_newReg(__name, __size) \
Arg __name = {0}; \

View File

@ -0,0 +1,21 @@
# '6' in binary is '110', '3' in binary is '011'.
# Bitwise XOR operation: '110' ^ '011' = '101' = '5' in decimal
assert 6 ^ 3 == 5
# '10' in binary is '1010', '6' in binary is '0110'.
# Bitwise XOR operation: '1010' ^ '0110' = '1100' = '12' in decimal
assert 10 ^ 6 == 12
# Start with '6' ('110' in binary)
value = 6
# Bitwise XOR and assign with '3' ('011' in binary), '110' ^ '011' = '101'
value ^= 3
assert value == 5
# Bitwise XOR and assign with '10' ('1010' in binary), '101' ^ '1010' = '1111'
value ^= 10
assert value == 15
print('PASS')

View File

@ -0,0 +1,31 @@
a = 1
a += -1 # Should result in 0
assert a == 0
a -= -1 # Subtracting -1 is same as adding 1, should result in 1
assert a == 1
a *= -1 # Should result in -1
assert a == -1
# Be careful with dividing by -1 if a is 0, it will raise a ZeroDivisionError
a /= -1 # Should result in 1
assert a == 1
a **= -1 # Should result in 1.0 (since a is 1)
assert a == 1.0
# Be careful with floordiv by -1 if a is 0, it will raise a ZeroDivisionError
a //= -1 # Should result in -1.0
assert a == -1.0
# Here onwards, comparison operators are used, they will return a boolean
assert (a >= -1) == True
assert (a <= -1) == True
assert (a != -1) == False
# Be careful with modulo by -1 if a is 0, it will raise a ZeroDivisionError
a %= -1 # Should result in 0
assert a == 0
print("PASS")

View File

@ -0,0 +1,20 @@
t = tuple()
assert type(t) == tuple
l = [1, 2, 3, 4, 5]
t = tuple(l)
assert type(t) == tuple
assert t[0] == 1
assert t[1] == 2
assert t[2] == 3
assert t[3] == 4
assert t[4] == 5
t = tuple('test')
assert type(t) == tuple
assert t[0] == 't'
assert t[1] == 'e'
assert t[2] == 's'
assert t[3] == 't'
print('PASS')

View File

@ -588,22 +588,22 @@ TEST(stddata, list_slice_issue) {
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(stddata, obj_newDict){
PikaObj* new_dict = obj_newDict(arg_newStr("a"), arg_newInt(1), arg_newStr("b"), arg_newInt(2), arg_newStr("c"), arg_newInt(3));
TEST(stddata, objDict_new){
PikaObj* new_dict = objDict_new(arg_newStr("a"), arg_newInt(1), arg_newStr("b"), arg_newInt(2), arg_newStr("c"), arg_newInt(3));
pika_platform_printf("%s\r\n", PikaStdData_Dict___str__(new_dict));
obj_deinit(new_dict);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(stddata, obj_newDict0){
PikaObj* new_dict = obj_newDict(NULL);
TEST(stddata, objDict_new0){
PikaObj* new_dict = objDict_new(NULL);
pika_platform_printf("%s\r\n", PikaStdData_Dict___str__(new_dict));
obj_deinit(new_dict);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(stddata, obj_newList0){
PikaObj* new_list = obj_newList(NULL);
TEST(stddata, objList_new0){
PikaObj* new_list = objList_new(NULL);
pika_platform_printf("%s\r\n", PikaStdData_List___str__(new_list));
obj_deinit(new_list);
EXPECT_EQ(pikaMemNow(), 0);