diff --git a/port/linux/package/pikascript/pikascript-core/BaseObj.c b/port/linux/package/pikascript/pikascript-core/BaseObj.c new file mode 100644 index 000000000..6c1742449 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/BaseObj.c @@ -0,0 +1,102 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define __PIKA_OBJ_CLASS_IMPLEMENT + +#include "BaseObj.h" +#include "PikaObj.h" +#include "TinyObj.h" +#include "dataMemory.h" +#include "dataString.h" +#include "dataStrs.h" + +Arg* arg_setMetaObj(char* objName, char* className, NewFun objPtr) { + Args buffs = {0}; + Arg* argNew = New_arg(NULL); + /* m means mate-object */ + argNew = arg_setPtr(argNew, objName, ARG_TYPE_MATE_OBJECT, (void*)objPtr); + strsDeinit(&buffs); + return argNew; +} + +int32_t obj_newObj(PikaObj* self, + char* objName, + char* className, + NewFun newFunPtr) { + /* add mate Obj, no inited */ + Arg* mateObj = arg_setMetaObj(objName, className, newFunPtr); + args_setArg(self->list, mateObj); + return 0; +} + +static void print_no_end(PikaObj* self, Args* args) { + obj_setErrorCode(self, 0); + char* res = args_print(args, "val"); + if (NULL == res) { + obj_setSysOut(self, "[error] print: can not print val"); + obj_setErrorCode(self, 1); + return; + } + /* not empty */ + if (strIsContain(res, '\\')) { + res = strsReplace(args, res, "\\n", "\n"); + res = strsReplace(args, res, "\\r", "\r"); + res = strsReplace(args, res, "\\t", "\t"); + } + __platform_printf("%s", res); +} + +void baseobj_print(PikaObj* self, Args* args) { + obj_setErrorCode(self, 0); + Arg* print_arg = args_getArg(args, "val"); + if (NULL != print_arg) { + if (arg_getType(print_arg) == ARG_TYPE_BYTES) { + arg_printBytes(print_arg); + return; + } + } + char* res = args_print(args, "val"); + if (NULL == res) { + obj_setSysOut(self, "[error] print: can not print val"); + obj_setErrorCode(self, 1); + return; + } + /* not empty */ + if (strIsContain(res, '\\')) { + res = strsReplace(args, res, "\\n", "\n"); + res = strsReplace(args, res, "\\r", "\r"); + res = strsReplace(args, res, "\\t", "\t"); + } + __platform_printf("%s\r\n", res); +} + +PikaObj* New_BaseObj(Args* args) { + PikaObj* self = New_TinyObj(args); + class_defineMethod(self, "print(val:any)", baseobj_print); + class_defineMethod(self, "printNoEnd(val:any)", print_no_end); + return self; +} diff --git a/port/linux/package/pikascript/pikascript-core/BaseObj.h b/port/linux/package/pikascript/pikascript-core/BaseObj.h new file mode 100644 index 000000000..12287a8e1 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/BaseObj.h @@ -0,0 +1,46 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _PikaObj_baseObj__H +#define _PikaObj_baseObj__H +#include "PikaObj.h" +#include "PikaVM.h" +#include "TinyObj.h" +#include "dataMemory.h" +PikaObj* New_BaseObj(Args* args); +int32_t obj_newObjFromClassLoader(PikaObj* self, + char* objPath, + char* classPath); +int32_t obj_import(PikaObj* self, char* className, NewFun classPtr); +int32_t obj_newObj(PikaObj* self, + char* objName, + char* className, + NewFun newFunPtr); +Arg* arg_setMetaObj(char* objName, char* className, NewFun objPtr); +void baseobj_print(PikaObj* self, Args* args); + +#endif diff --git a/port/linux/package/pikascript/pikascript-core/CMakeLists.txt b/port/linux/package/pikascript/pikascript-core/CMakeLists.txt new file mode 100644 index 000000000..287833f30 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/CMakeLists.txt @@ -0,0 +1,9 @@ +#设置 BINARY 为项目名IndexProject +set(BINARY ${CMAKE_PROJECT_NAME}) + +file(GLOB_RECURSE SOURCES LIST_DIRECTORIES true *.h *.c) +set(SOURCES ${SOURCES}) + +add_library(${BINARY}-core + STATIC + ${SOURCES}) diff --git a/port/linux/package/pikascript/pikascript-core/PikaObj.c b/port/linux/package/pikascript/pikascript-core/PikaObj.c new file mode 100644 index 000000000..d22f654e7 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/PikaObj.c @@ -0,0 +1,889 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define __PIKA_OBJ_CLASS_IMPLEMENT +#include "PikaObj.h" +#include "BaseObj.h" +#include "PikaPlatform.h" +#include "dataArgs.h" +#include "dataMemory.h" +#include "dataString.h" +#include "dataStrs.h" + +int fast_atoi(char* src) { + const char* p = src; + static const uint64_t a[][10] = { + {0, 1e0, 2e0, 3e0, 4e0, 5e0, 6e0, 7e0, 8e0, 9e0}, + {0, 1e1, 2e1, 3e1, 4e1, 5e1, 6e1, 7e1, 8e1, 9e1}, + {0, 1e2, 2e2, 3e2, 4e2, 5e2, 6e2, 7e2, 8e2, 9e2}, + {0, 1e3, 2e3, 3e3, 4e3, 5e3, 6e3, 7e3, 8e3, 9e3}, + {0, 1e4, 2e4, 3e4, 4e4, 5e4, 6e4, 7e4, 8e4, 9e4}, + {0, 1e5, 2e5, 3e5, 4e5, 5e5, 6e5, 7e5, 8e5, 9e5}, + {0, 1e6, 2e6, 3e6, 4e6, 5e6, 6e6, 7e6, 8e6, 9e6}, + {0, 1e7, 2e7, 3e7, 4e7, 5e7, 6e7, 7e7, 8e7, 9e7}, + {0, 1e8, 2e8, 3e8, 4e8, 5e8, 6e8, 7e8, 8e8, 9e8}, + {0, 1e9, 2e9, 3e9, 4e9, 5e9, 6e9, 7e9, 8e9, 9e9}, + }; + uint16_t size = strGetSize(src); + p = p + size - 1; + if (*p) { + int s = 0; + const uint64_t* n = a[0]; + while (p != src) { + s += n[(*p - '0')]; + n += 10; + p--; + } + if (*p == '-') { + return -s; + } + return s + n[(*p - '0')]; + } + return 0; +} + +static uint16_t const str100p[100] = { + 0x3030, 0x3130, 0x3230, 0x3330, 0x3430, 0x3530, 0x3630, 0x3730, 0x3830, + 0x3930, 0x3031, 0x3131, 0x3231, 0x3331, 0x3431, 0x3531, 0x3631, 0x3731, + 0x3831, 0x3931, 0x3032, 0x3132, 0x3232, 0x3332, 0x3432, 0x3532, 0x3632, + 0x3732, 0x3832, 0x3932, 0x3033, 0x3133, 0x3233, 0x3333, 0x3433, 0x3533, + 0x3633, 0x3733, 0x3833, 0x3933, 0x3034, 0x3134, 0x3234, 0x3334, 0x3434, + 0x3534, 0x3634, 0x3734, 0x3834, 0x3934, 0x3035, 0x3135, 0x3235, 0x3335, + 0x3435, 0x3535, 0x3635, 0x3735, 0x3835, 0x3935, 0x3036, 0x3136, 0x3236, + 0x3336, 0x3436, 0x3536, 0x3636, 0x3736, 0x3836, 0x3936, 0x3037, 0x3137, + 0x3237, 0x3337, 0x3437, 0x3537, 0x3637, 0x3737, 0x3837, 0x3937, 0x3038, + 0x3138, 0x3238, 0x3338, 0x3438, 0x3538, 0x3638, 0x3738, 0x3838, 0x3938, + 0x3039, 0x3139, 0x3239, 0x3339, 0x3439, 0x3539, 0x3639, 0x3739, 0x3839, + 0x3939, +}; + +char* fast_itoa(char* buf, uint32_t val) { + char* p = &buf[10]; + *p = '\0'; + while (val >= 100) { + uint32_t const old = val; + + p -= 2; + val /= 100; + __platform_memcpy(p, &str100p[old - (val * 100)], sizeof(uint16_t)); + } + p -= 2; + __platform_memcpy(p, &str100p[val], sizeof(uint16_t)); + return &p[val < 10]; +} + +int32_t deinitEachSubObj(Arg* argEach, Args* handleArgs) { + if (NULL != handleArgs) { + /* error: tOhis handle not need handle args */ + return 1; + } + ArgType type = arg_getType(argEach); + /* deinit sub object */ + if (type == ARG_TYPE_OBJECT) { + PikaObj* subObj = arg_getPtr(argEach); + obj_deinit(subObj); + } + return 0; +} + +void deinitAllSubObj(PikaObj* self) { + Args* args = self->list; + args_foreach(args, deinitEachSubObj, NULL); +} + +int32_t obj_deinit(PikaObj* self) { + deinitAllSubObj(self); + args_deinit(self->list); + pikaFree(self, sizeof(PikaObj)); + self = NULL; + return 0; +} + +int32_t obj_enable(PikaObj* self) { + obj_setInt(self, "isEnable", 1); + return 0; +} + +int32_t obj_disable(PikaObj* self) { + obj_setInt(self, "isEnable", 0); + return 0; +} + +int32_t obj_setInt(PikaObj* self, char* argPath, int64_t val) { + PikaObj* obj = obj_getObj(self, argPath, 1); + if (NULL == obj) { + /* [error] object no found */ + return 1; + } + char* name = strPointToLastToken(argPath, '.'); + args_setInt(obj->list, name, val); + return 0; +} + +int32_t obj_setPtr(PikaObj* self, char* argPath, void* pointer) { + PikaObj* obj = obj_getObj(self, argPath, 1); + if (NULL == obj) { + return 1; + } + char* name = strPointToLastToken(argPath, '.'); + args_setPtr(obj->list, name, pointer); + return 0; +} + +int32_t obj_setRefObject(PikaObj* self, char* argPath, void* pointer) { + PikaObj* obj = obj_getObj(self, argPath, 1); + if (NULL == obj) { + return 1; + } + char* name = strPointToLastToken(argPath, '.'); + args_setRefObject(obj->list, name, pointer); + return 0; +} + +int32_t obj_setFloat(PikaObj* self, char* argPath, float value) { + PikaObj* obj = obj_getObj(self, argPath, 1); + if (NULL == obj) { + return 1; + } + char* name = strPointToLastToken(argPath, '.'); + args_setFloat(obj->list, name, value); + return 0; +} + +int32_t obj_setStr(PikaObj* self, char* argPath, char* str) { + PikaObj* obj = obj_getObj(self, argPath, 1); + if (NULL == obj) { + return 1; + } + char* name = strPointToLastToken(argPath, '.'); + args_setStr(obj->list, name, str); + return 0; +} + +int32_t obj_setBytes(PikaObj* self, char* argPath, uint8_t* src, size_t size) { + PikaObj* obj = obj_getObj(self, argPath, 1); + if (NULL == obj) { + return 1; + } + char* name = strPointToLastToken(argPath, '.'); + args_setBytes(obj->list, name, src, size); + return 0; +} + +int64_t obj_getInt(PikaObj* self, char* argPath) { + PikaObj* obj = obj_getObj(self, argPath, 1); + if (NULL == obj) { + return -999999999; + } + char* argName = strPointToLastToken(argPath, '.'); + int res = args_getInt(obj->list, argName); + return res; +} + +Arg* obj_getArg(PikaObj* self, char* argPath) { + PikaObj* obj = obj_getObj(self, argPath, 1); + if (NULL == obj) { + return NULL; + } + char* argName = strPointToLastToken(argPath, '.'); + Arg* res = args_getArg(obj->list, argName); + return res; +} + +uint8_t* obj_getBytes(PikaObj* self, char* argPath) { + PikaObj* obj = obj_getObj(self, argPath, 1); + if (NULL == obj) { + return NULL; + } + char* argName = strPointToLastToken(argPath, '.'); + return args_getBytes(obj->list, argName); +} + +size_t obj_getBytesSize(PikaObj* self, char* argPath) { + PikaObj* obj = obj_getObj(self, argPath, 1); + if (NULL == obj) { + return 0; + } + char* argName = strPointToLastToken(argPath, '.'); + return args_getBytesSize(obj->list, argName); +} + +size_t obj_loadMem(PikaObj* self, char* argPath, uint8_t* out_buff) { + size_t size_mem = obj_getBytesSize(self, argPath); + void* src = obj_getBytes(self, argPath); + if (0 == size_mem) { + return 0; + } + if (NULL == src) { + return 0; + } + __platform_memcpy(out_buff, src, size_mem); + return size_mem; +} + +static int32_t __obj_setArg(PikaObj* self, + char* argPath, + Arg* arg, + uint8_t is_copy) { + /* setArg would copy arg */ + PikaObj* obj = obj_getObj(self, argPath, 1); + if (NULL == obj) { + /* object no found */ + return 1; + } + char* argName = strPointToLastToken(argPath, '.'); + Arg* newArg; + if (is_copy) { + newArg = arg_copy(arg); + } else { + newArg = arg; + } + newArg = arg_setName(newArg, argName); + args_setArg(obj->list, newArg); + return 0; +} + +int32_t obj_setArg(PikaObj* self, char* argPath, Arg* arg) { + return __obj_setArg(self, argPath, arg, 1); +}; + +int32_t obj_setArg_noCopy(PikaObj* self, char* argPath, Arg* arg) { + return __obj_setArg(self, argPath, arg, 0); +} + +void* obj_getPtr(PikaObj* self, char* argPath) { + PikaObj* obj = obj_getObj(self, argPath, 1); + if (NULL == obj) { + return NULL; + } + char* argName = strPointToLastToken(argPath, '.'); + void* res = args_getPtr(obj->list, argName); + return res; +} + +float obj_getFloat(PikaObj* self, char* argPath) { + PikaObj* obj = obj_getObj(self, argPath, 1); + if (NULL == obj) { + return -999.999; + } + char* argName = strPointToLastToken(argPath, '.'); + float res = args_getFloat(obj->list, argName); + return res; +} + +char* obj_getStr(PikaObj* self, char* argPath) { + PikaObj* obj = obj_getObj(self, argPath, 1); + if (NULL == obj) { + return NULL; + } + char* argName = strPointToLastToken(argPath, '.'); + char* res = args_getStr(obj->list, argName); + return res; +} + +int32_t obj_load(PikaObj* self, Args* args, char* name) { + args_copyArgByName(args, name, self->list); + return 0; +} + +int32_t obj_freeObj(PikaObj* self, char* objPath) { + PikaObj* obj = obj_getPtr(self, objPath); + obj_deinit(obj); + return 0; +} + +char* obj_print(PikaObj* self, char* name) { + if (NULL == self) { + return NULL; + } + return args_print(self->list, name); +} + +PikaObj* obj_getClassObjByNewFun(PikaObj* context, + char* name, + NewFun newClassFun) { + Args* initArgs = New_args(NULL); + PikaObj* thisClass = newClassFun(initArgs); + obj_setPtr(thisClass, "_clsptr", (void*)newClassFun); + obj_setInt(thisClass, "_refcnt", 0); + args_deinit(initArgs); + return thisClass; +} + +Arg* obj_getMethodArg(PikaObj* obj, char* methodPath) { + Arg* method = NULL; + char* methodName = strPointToLastToken(methodPath, '.'); + method = obj_getArg(obj, methodName); + PikaObj* methodHostClass; + if (NULL != method) { + method = arg_copy(method); + goto exit; + } + methodHostClass = obj_getClassObj(obj); + method = arg_copy(obj_getArg(methodHostClass, methodName)); + obj_deinit(methodHostClass); +exit: + return method; +} + +PikaObj* obj_getClassObj(PikaObj* obj) { + NewFun classPtr = (NewFun)obj_getPtr(obj, "_clsptr"); + PikaObj* classObj = obj_getClassObjByNewFun(obj, "", classPtr); + return classObj; +} + +void* getNewClassObjFunByName(PikaObj* obj, char* name) { + char* classPath = name; + /* init the subprocess */ + void* newClassObjFun = args_getPtr(obj->list, classPath); + return newClassObjFun; +} + +int32_t __foreach_removeMethodInfo(Arg* argNow, Args* argList) { + if (arg_getType(argNow) == ARG_TYPE_NATIVE_METHOD) { + args_removeArg(argList, argNow); + return 0; + } + return 0; +} + +PikaObj* removeMethodInfo(PikaObj* thisClass) { +#if PIKA_METHOD_CACHE_ENABLE +#else + args_foreach(thisClass->list, __foreach_removeMethodInfo, thisClass->list); +#endif + return thisClass; +} + +PikaObj* newObjFromFun(NewFun newObjFun) { + PikaObj* thisClass = obj_getClassObjByNewFun(NULL, "", newObjFun); + return removeMethodInfo(thisClass); +} + +extern PikaObj* __pikaMain; +PikaObj* newRootObj(char* name, NewFun newObjFun) { + PikaObj* newObj = newObjFromFun(newObjFun); + __pikaMain = newObj; + return newObj; +} + +Arg* obj_getRefArg(PikaObj* self) { + return arg_setPtr(NULL, "", ARG_TYPE_FREE_OBJECT, self); +} + +Arg* newFreeObjArg(NewFun newObjFun) { + PikaObj* newObj = newObjFromFun(newObjFun); + Arg* objArg = arg_setPtr(NULL, "", ARG_TYPE_FREE_OBJECT, newObj); + return objArg; +} + +Arg* obj_newObjInPackage(NewFun newObjFun) { + return newFreeObjArg(newObjFun); +} + +static PikaObj* __initObj(PikaObj* obj, char* name) { + PikaObj* res = NULL; + NewFun newObjFun = (NewFun)getNewClassObjFunByName(obj, name); + Args buffs = {0}; + PikaObj* thisClass; + PikaObj* newObj; + if (NULL == newObjFun) { + /* no such object */ + res = NULL; + goto exit; + } + thisClass = obj_getClassObjByNewFun(obj, name, newObjFun); + newObj = removeMethodInfo(thisClass); + + args_setPtrWithType(obj->list, name, ARG_TYPE_OBJECT, newObj); + res = obj_getPtr(obj, name); + goto exit; +exit: + strsDeinit(&buffs); + return res; +} + +PikaObj* obj_getObjDirect(PikaObj* self, char* name) { + if (NULL == self) { + return NULL; + } + /* finded object, check type*/ + ArgType type = args_getType(self->list, name); + /* found mate Object */ + if (type == ARG_TYPE_MATE_OBJECT) { + return __initObj(self, name); + } + /* found Objcet */ + if (type == ARG_TYPE_OBJECT || type == ARG_TYPE_REF_OBJECT) { + return args_getPtr(self->list, name); + } + return NULL; +} + +PikaObj* obj_getObj(PikaObj* self, char* objPath, int32_t keepDeepth) { + char objPath_buff[PIKA_PATH_BUFF_SIZE]; + __platform_memcpy(objPath_buff, objPath, strGetSize(objPath) + 1); + char token_buff[PIKA_NAME_BUFF_SIZE] = {0}; + int32_t token_num = strGetTokenNum(objPath, '.'); + PikaObj* obj = self; + for (int32_t i = 0; i < token_num - keepDeepth; i++) { + char* token = strPopToken(token_buff, objPath_buff, '.'); + obj = obj_getObjDirect(obj, token); + if (obj == NULL) { + goto exit; + } + } + goto exit; +exit: + return obj; +} + +Method methodArg_getPtr(Arg* method_arg) { + uint32_t size_ptr = sizeof(void*); + void* info = arg_getContent(method_arg); + void* ptr = NULL; + __platform_memcpy(&ptr, info, size_ptr); + return (Method)ptr; +} + +char* methodArg_getTypeList(Arg* method_arg, Args* buffs) { + char* method_dec = strsCopy(buffs, methodArg_getDec(method_arg)); + return strsCut(buffs, method_dec, '(', ')'); +} + +Method obj_getNativeMethod(PikaObj* self, char* method_name) { + Arg* method_arg = obj_getMethodArg(self, method_name); + if (NULL == method_arg) { + return NULL; + } + Method res = methodArg_getPtr(method_arg); + arg_deinit(method_arg); + return res; +} + +ByteCodeFrame* methodArg_getBytecodeFrame(Arg* method_arg) { + uint32_t size_ptr = sizeof(void*); + void* info = arg_getContent(method_arg) + size_ptr; + ByteCodeFrame* ptr = NULL; + __platform_memcpy(&ptr, info, size_ptr); + return ptr; +} + +char* methodArg_getDec(Arg* method_arg) { + uint32_t size_ptr = sizeof(void*); + void* info = arg_getContent(method_arg); + return (char*)((uintptr_t)info + 2 * size_ptr); +} + +static void obj_saveMethodInfo(PikaObj* self, MethodInfo* method_info) { + Args buffs = {0}; + char* pars = strsRemovePrefix(&buffs, method_info->dec, method_info->name); + method_info->pars = pars; + Arg* arg = New_arg(NULL); + uint32_t size_pars = strGetSize(pars); + uintptr_t method_info_bytecode_frame = + (uintptr_t)method_info->bytecode_frame; + arg = + arg_setPtr(arg, method_info->name, method_info->type, method_info->ptr); + arg = arg_append(arg, &(method_info_bytecode_frame), + sizeof(method_info_bytecode_frame)); + arg = arg_append(arg, method_info->pars, size_pars + 1); + args_setArg(self->list, arg); + strsDeinit(&buffs); +} +static int32_t __class_defineMethodWithType(PikaObj* self, + char* declearation, + Method methodPtr, + ArgType method_type, + ByteCodeFrame* bytecode_frame) { + int32_t size = strGetSize(declearation); + int32_t res = 0; + Args buffs = {0}; + char* cleanDeclearation = + strDeleteChar(args_getBuff(&buffs, size), declearation, ' '); + char* methodPath = + strGetFirstToken(args_getBuff(&buffs, size), cleanDeclearation, '('); + + PikaObj* methodHost = obj_getObj(self, methodPath, 1); + MethodInfo method_info = {0}; + char* methodName; + if (NULL == methodHost) { + /* no found method object */ + res = 1; + goto exit; + } + methodName = strPointToLastToken(methodPath, '.'); + method_info.dec = cleanDeclearation; + method_info.name = methodName; + method_info.ptr = (void*)methodPtr; + method_info.type = method_type; + method_info.bytecode_frame = bytecode_frame; + obj_saveMethodInfo(methodHost, &method_info); + res = 0; + goto exit; +exit: + strsDeinit(&buffs); + return res; +} + +/* define a constructor method */ +int32_t class_defineConstructor(PikaObj* self, + char* declearation, + Method methodPtr) { + return __class_defineMethodWithType(self, declearation, methodPtr, + ARG_TYPE_NATIVE_CONSTRUCTOR_METHOD, + NULL); +} + +/* define a native method as default */ +int32_t class_defineMethod(PikaObj* self, + char* declearation, + Method methodPtr) { + return __class_defineMethodWithType(self, declearation, methodPtr, + ARG_TYPE_NATIVE_METHOD, NULL); +} + +/* define object method, object method is which startwith (self) */ +int32_t class_defineRunTimeConstructor(PikaObj* self, + char* declearation, + Method methodPtr, + ByteCodeFrame* bytecode_frame) { + return __class_defineMethodWithType(self, declearation, methodPtr, + ARG_TYPE_CONSTRUCTOR_METHOD, + bytecode_frame); +} + +/* define object method, object method is which startwith (self) */ +int32_t class_defineObjectMethod(PikaObj* self, + char* declearation, + Method methodPtr, + ByteCodeFrame* bytecode_frame) { + return __class_defineMethodWithType(self, declearation, methodPtr, + ARG_TYPE_OBJECT_METHOD, bytecode_frame); +} + +/* define a static method as default */ +int32_t class_defineStaticMethod(PikaObj* self, + char* declearation, + Method methodPtr, + ByteCodeFrame* bytecode_frame) { + return __class_defineMethodWithType(self, declearation, methodPtr, + ARG_TYPE_STATIC_METHOD, bytecode_frame); +} + +PIKA_WEAK int __runExtern_contral(PikaObj* self, char* cmd) { + return 0; +} + +VMParameters* obj_runDirect(PikaObj* self, char* cmd) { + return pikaVM_run(self, cmd); +} + +int32_t obj_removeArg(PikaObj* self, char* argPath) { + PikaObj* objHost = obj_getObj(self, argPath, 1); + Arg* obj_arg = obj_getArg(self, argPath); + char* argName; + int32_t res; + if (ARG_TYPE_OBJECT == arg_getType(obj_arg)) { + obj_deinit(arg_getPtr(obj_arg)); + } + int32_t err = 0; + if (NULL == objHost) { + /* [error] object no found */ + err = 1; + goto exit; + } + argName = strPointToLastToken(argPath, '.'); + res = args_removeArg(objHost->list, args_getArg(objHost->list, argName)); + if (1 == res) { + /*[error] not found arg*/ + err = 2; + goto exit; + } + goto exit; +exit: + return err; +} + +int32_t obj_isArgExist(PikaObj* self, char* argPath) { + PikaObj* obj = obj_getObj(self, argPath, 1); + int32_t res = 0; + char* argName; + Arg* arg; + if (NULL == obj) { + /* [error] object no found */ + res = 1; + goto exit; + } + argName = strPointToLastToken(argPath, '.'); + arg = args_getArg(obj->list, argName); + if (NULL == arg) { + /* no found arg */ + res = 0; + goto exit; + } + /* found arg */ + res = 1; + goto exit; + +exit: + return res; +} + +void obj_runNoRes(PikaObj* slef, char* cmd) { + /* unsafe, nothing would happend when error occord */ + obj_runDirect(slef, cmd); +} + +void obj_run(PikaObj* self, char* cmd) { + obj_runDirect(self, cmd); +} + +void obj_runNativeMethod(PikaObj* self, char* method_name, Args* args) { + Method native_method = obj_getNativeMethod(self, method_name); + if (NULL == native_method) { + return; + } + native_method(self, args); +} + +static void __clearBuff(char* buff, int size) { + for (int i = 0; i < size; i++) { + buff[i] = 0; + } +} + +void obj_shellLineProcess(PikaObj* self, + __obj_shellLineHandler_t __lineHandler_fun, + struct shell_config* cfg) { + Args buffs = {0}; + char* rxBuff = args_getBuff(&buffs, PIKA_LINE_BUFF_SIZE); + char* input_line = NULL; + uint8_t is_in_block = 0; + __platform_printf(cfg->prefix); + while (1) { + char inputChar = __platform_getchar(); +#ifndef __linux + __platform_printf("%c", inputChar); +#endif + if ((inputChar == '\b') || (inputChar == 127)) { + uint32_t size = strGetSize(rxBuff); + if (size == 0) { + __platform_printf(" "); + continue; + } + __platform_printf(" \b"); + rxBuff[size - 1] = 0; + continue; + } + if (inputChar != '\r' && inputChar != '\n') { + strAppendWithSize(rxBuff, &inputChar, 1); + continue; + } + if ((inputChar == '\r') || (inputChar == '\n')) { +#ifndef __linux + __platform_printf("\r\n"); +#endif + /* still in block */ + if (is_in_block) { + /* load new line into buff */ + Args buffs = {0}; + char _n = '\n'; + strAppendWithSize(rxBuff, &_n, 1); + char* shell_buff_new = + strsAppend(&buffs, obj_getStr(self, "shell_buff"), rxBuff); + obj_setStr(self, "shell_buff", shell_buff_new); + strsDeinit(&buffs); + /* go out from block */ + if (rxBuff[0] != ' ') { + is_in_block = 0; + input_line = obj_getStr(self, "shell_buff"); + if (SHELL_STATE_EXIT == + __lineHandler_fun(self, input_line)) { + break; + } + __platform_printf(">>> "); + } else { + __platform_printf("... "); + } + __clearBuff(rxBuff, PIKA_LINE_BUFF_SIZE); + continue; + } + if (0 != strGetSize(rxBuff)) { + /* go in block */ + if (rxBuff[strGetSize(rxBuff) - 1] == ':') { + is_in_block = 1; + char _n = '\n'; + strAppendWithSize(rxBuff, &_n, 1); + obj_setStr(self, "shell_buff", rxBuff); + __clearBuff(rxBuff, PIKA_LINE_BUFF_SIZE); + __platform_printf("... "); + continue; + } + } + input_line = rxBuff; + if (SHELL_STATE_EXIT == __lineHandler_fun(self, input_line)) { + break; + } + __platform_printf(cfg->prefix); + + __clearBuff(rxBuff, PIKA_LINE_BUFF_SIZE); + continue; + } + } + strsDeinit(&buffs); +} + +static enum shell_state __obj_shellLineHandler_debuger(PikaObj* self, + char* input_line) { + /* exit */ + if (strEqu("exit()", input_line)) { + /* exit pika shell */ + return SHELL_STATE_EXIT; + } + /* run single line */ + obj_run(self, input_line); + return SHELL_STATE_CONTINUE; +} + +void pikaScriptShell(PikaObj* self) { + struct shell_config cfg = { + .prefix = ">>> ", + }; + obj_shellLineProcess(self, __obj_shellLineHandler_debuger, &cfg); +} + +void obj_setErrorCode(PikaObj* self, int32_t errCode) { + obj_setInt(self, "__errCode", errCode); +} + +int32_t obj_getErrorCode(PikaObj* self) { + if (!obj_isArgExist(self, "__errCode")) { + return 0; + } + return obj_getInt(self, "__errCode"); +} + +void args_setErrorCode(Args* args, int32_t errCode) { + args_setInt(args, "__errCode", errCode); +} + +int32_t args_getErrorCode(Args* args) { + if (!args_isArgExist(args, "__errCode")) { + return 0; + } + return args_getInt(args, "__errCode"); +} + +void obj_setSysOut(PikaObj* self, char* str) { + // obj_setStr(self, "__sysOut", str); + args_setSysOut(self->list, str); +} + +char* obj_getSysOut(PikaObj* self) { + return obj_getStr(self, "__sysOut"); +} + +char* args_getSysOut(Args* args) { + return args_getStr(args, "__sysOut"); +} + +void args_setSysOut(Args* args, char* str) { + // args_setStr(args, "__sysOut", str); + if (NULL == str) { + return; + } + if (strEqu("", str)) { + return; + } + __platform_printf("%s\r\n", str); +} + +void obj_sysPrintf(PikaObj* self, char* fmt, ...) { + va_list args; + va_start(args, fmt); + char sysOut[128] = {0}; + __platform_vsprintf(sysOut, fmt, args); + obj_setSysOut(self, sysOut); + va_end(args); +} + +void method_returnBytes(Args* args, uint8_t* val) { + args_setBytes(args, "return", val, PIKA_BYTES_DEFAULT_SIZE); +} + +void method_returnStr(Args* args, char* val) { + args_setStr(args, "return", val); +} + +void method_returnInt(Args* args, int32_t val) { + args_setInt(args, "return", val); +} + +void method_returnFloat(Args* args, float val) { + args_setFloat(args, "return", val); +} + +void method_returnPtr(Args* args, void* val) { + args_setPtr(args, "return", val); +} + +void method_returnArg(Args* args, Arg* arg) { + arg = arg_setName(arg, "return"); + args_setArg(args, arg); +} + +int32_t method_getInt(Args* args, char* argName) { + return args_getInt(args, argName); +} + +float method_getFloat(Args* args, char* argName) { + return args_getFloat(args, argName); +} + +char* method_getStr(Args* args, char* argName) { + return args_getStr(args, argName); +} + +PikaObj* New_PikaObj(void) { + PikaObj* self = pikaMalloc(sizeof(PikaObj)); + /* List */ + self->list = New_args(NULL); + return self; +} + +void obj_refcntInc(PikaObj* self) { + obj_setInt(self, "_refcnt", obj_getInt(self, "_refcnt") + 1); +} + +void obj_refcntDec(PikaObj* self) { + obj_setInt(self, "_refcnt", obj_getInt(self, "_refcnt") - 1); +} + +int obj_refcntNow(PikaObj* self) { + return obj_getInt(self, "_refcnt"); +} diff --git a/port/linux/package/pikascript/pikascript-core/PikaObj.h b/port/linux/package/pikascript/pikascript-core/PikaObj.h new file mode 100644 index 000000000..a378034c8 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/PikaObj.h @@ -0,0 +1,237 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _Process__H +#define _Process__H + +/*! \NOTE: Make sure #include "plooc_class.h" is close to the class definition + */ +//#define __PLOOC_CLASS_USE_STRICT_TEMPLATE__ + +#if defined(__PIKA_OBJ_CLASS_IMPLEMENT) +#define __PLOOC_CLASS_IMPLEMENT__ +#elif defined(__PIKA_OBJ_CLASS_INHERIT__) +#define __PLOOC_CLASS_INHERIT__ +#endif + +#include "__pika_ooc.h" + +#include "dataArgs.h" +#include "dataLink.h" +#include "dataMemory.h" + +typedef struct InstructUnit_t { + uint8_t deepth; + uint8_t isNewLine_instruct; + uint16_t const_pool_index; +} InstructUnit; + +typedef struct ConstPool_t ConstPool; +struct ConstPool_t { + Arg* arg_buff; + uint16_t content_offset_now; + uint16_t size; + void* content_start; + void (*output_redirect_fun)(ConstPool* self, char* content); + FILE* output_f; +}; + +typedef struct InstructArray_t InstructArray; +struct InstructArray_t { + Arg* arg_buff; + uint16_t content_offset_now; + uint16_t size; + void* content_start; + void (*output_redirect_fun)(InstructArray* self, InstructUnit* ins_unit); + FILE* output_f; +}; + +typedef struct ByteCodeFrame_t { + ConstPool const_pool; + InstructArray instruct_array; +} ByteCodeFrame; + +typedef struct PikaObj_t { + /* list */ + Args* list; +} PikaObj; + +typedef PikaObj* (*NewFun)(Args* args); +typedef PikaObj* (*InitFun)(PikaObj* self, Args* args); +typedef PikaObj VMParameters; +typedef void (*Method)(PikaObj* self, Args* args); + +typedef struct MethodInfo_t { + char* name; + char* dec; + char* ptr; + char* pars; + ArgType type; + ByteCodeFrame* bytecode_frame; +} MethodInfo; + +/* operation */ +int32_t obj_deinit(PikaObj* self); +int32_t obj_init(PikaObj* self, Args* args); +int32_t obj_update(PikaObj* self); +int32_t obj_enable(PikaObj* self); +int32_t obj_disable(PikaObj* self); + +// arg type operations +int32_t obj_setInt(PikaObj* self, char* argPath, int64_t val); +int32_t obj_setRefObject(PikaObj* self, char* argPath, void* pointer); +int32_t obj_setPtr(PikaObj* self, char* argPath, void* pointer); +int32_t obj_setFloat(PikaObj* self, char* argPath, float value); +int32_t obj_setStr(PikaObj* self, char* argPath, char* str); +int32_t obj_setArg(PikaObj* self, char* argPath, Arg* arg); +int32_t obj_setArg_noCopy(PikaObj* self, char* argPath, Arg* arg); +int32_t obj_setBytes(PikaObj* self, char* argPath, uint8_t* src, size_t size); + +void* obj_getPtr(PikaObj* self, char* argPath); +float obj_getFloat(PikaObj* self, char* argPath); +char* obj_getStr(PikaObj* self, char* argPath); +int64_t obj_getInt(PikaObj* self, char* argPath); +Arg* obj_getArg(PikaObj* self, char* argPath); +uint8_t* obj_getBytes(PikaObj* self, char* argPath); +size_t obj_getBytesSize(PikaObj* self, char* argPath); +size_t obj_loadMem(PikaObj* self, char* argPath, uint8_t* out_buff); + +char* obj_print(PikaObj* self, char* name); + +// args operations +int32_t obj_load(PikaObj* self, Args* args, char* name); + +// subObject +int32_t obj_addOther(PikaObj* self, char* subObjectName, void* new_projcetFun); +int32_t obj_setObjWithoutClass(PikaObj* self, + char* subObjectName, + void* new_projcetFun); +PikaObj* obj_getObjDirect(PikaObj* self, char* name); +PikaObj* obj_getObj(PikaObj* self, char* processPathectory, int32_t deepth); + +// subProcess +int32_t obj_freeObj(PikaObj* self, char* subObjectName); + +/* method */ +int32_t class_defineMethod(PikaObj* self, char* declearation, Method methodPtr); + +int32_t class_defineObjectMethod(PikaObj* self, + char* declearation, + Method methodPtr, + ByteCodeFrame* bytecode_frame); + +int32_t class_defineStaticMethod(PikaObj* self, + char* declearation, + Method methodPtr, + ByteCodeFrame* bytecode_frame); + +int32_t class_defineConstructor(PikaObj* self, + char* declearation, + Method methodPtr); + +int32_t class_defineRunTimeConstructor(PikaObj* self, + char* declearation, + Method methodPtr, + ByteCodeFrame* bytecode_frame); + +int32_t obj_removeArg(PikaObj* self, char* argPath); +int32_t obj_isArgExist(PikaObj* self, char* argPath); +PikaObj* obj_getClassObjByNewFun(PikaObj* self, char* name, NewFun newClassFun); +PikaObj* newRootObj(char* name, NewFun newObjFun); +PikaObj* obj_getClassObj(PikaObj* obj); +Arg* obj_getMethodArg(PikaObj* obj, char* methodPath); + +void obj_setErrorCode(PikaObj* self, int32_t errCode); +int32_t obj_getErrorCode(PikaObj* self); +void obj_setSysOut(PikaObj* self, char* str); +char* args_getSysOut(Args* args); +void args_setErrorCode(Args* args, int32_t errCode); +int32_t args_getErrorCode(Args* args); +void args_setSysOut(Args* args, char* str); +char* obj_getSysOut(PikaObj* self); +void obj_sysPrintf(PikaObj* self, char* fmt, ...); +uint8_t obj_getAnyArg(PikaObj* self, + char* targetArgName, + char* sourceArgPath, + Args* targetArgs); + +void method_returnStr(Args* args, char* val); +void method_returnInt(Args* args, int32_t val); +void method_returnFloat(Args* args, float val); +void method_returnPtr(Args* args, void* val); +int32_t method_getInt(Args* args, char* argName); +float method_getFloat(Args* args, char* argName); +char* method_getStr(Args* args, char* argName); +void method_returnArg(Args* args, Arg* arg); +char* methodArg_getDec(Arg* method_arg); +char* methodArg_getTypeList(Arg* method_arg, Args* buffs); +ByteCodeFrame* methodArg_getBytecodeFrame(Arg* method_arg); +Method methodArg_getPtr(Arg* method_arg); + +void obj_runNoRes(PikaObj* slef, char* cmd); +void obj_run(PikaObj* self, char* cmd); +VMParameters* obj_runDirect(PikaObj* self, char* cmd); +PikaObj* New_PikaObj(void); + +/* tools */ +int fast_atoi(char* src); +char* fast_itoa(char* buf, uint32_t val); + +/* shell */ +void pikaScriptShell(PikaObj* self); +enum shell_state { SHELL_STATE_CONTINUE, SHELL_STATE_EXIT }; +typedef enum shell_state (*__obj_shellLineHandler_t)(PikaObj*, char*); + +struct shell_config { + char* prefix; +}; + +void obj_shellLineProcess(PikaObj* self, + __obj_shellLineHandler_t __lineHandler_fun, + struct shell_config* cfg); + +/* + need implament : + __platform_fopen() + __platform_fwrite() + __platform_fclose() +*/ +int pikaCompile(char* output_file_name, char* py_lines); +Method obj_getNativeMethod(PikaObj* self, char* method_name); +void obj_runNativeMethod(PikaObj* self, char* method_name, Args* args); +Arg* newFreeObjArg(NewFun newObjFun); +Arg* obj_newObjInPackage(NewFun newObjFun); + +void obj_refcntInc(PikaObj* self); +void obj_refcntDec(PikaObj* self); +int obj_refcntNow(PikaObj* self); + +#define PIKA_PYTHON_BEGIN +#define PIKA_PYTHON(x) +#define PIKA_PYTHON_END + +#endif diff --git a/port/linux/package/pikascript/pikascript-core/PikaObj.py b/port/linux/package/pikascript/pikascript-core/PikaObj.py new file mode 100644 index 000000000..7e8d024c1 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/PikaObj.py @@ -0,0 +1,18 @@ +class TinyObj: + pass + + +class BaseObj(TinyObj): + pass + +class pointer: + pass + +def print(val: any): + pass + +def printNoEnd(val: any): + pass + +def taskLoop(task: any): + pass diff --git a/port/linux/package/pikascript/pikascript-core/PikaParser.c b/port/linux/package/pikascript/pikascript-core/PikaParser.c new file mode 100644 index 000000000..85e9bc857 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/PikaParser.c @@ -0,0 +1,2065 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "PikaParser.h" +#include "BaseObj.h" +#include "PikaObj.h" +#include "dataQueue.h" +#include "dataQueueObj.h" +#include "dataStack.h" +#include "dataStrs.h" + +/* local head */ +typedef QueueObj AST; +char* AST_toPikaASM(AST* ast, Args* outBuffs); +char* Lexer_getTokens(Args* outBuffs, char* stmt); +int32_t AST_deinit(AST* ast); +char* Parser_multiLineToAsm(Args* outBuffs, char* multiLine); +uint8_t Parser_isContainToken(char* tokens, + enum TokenType token_type, + char* pyload); +void ParserState_init(struct ParserState* ps); +void ParserState_parse(struct ParserState* ps, char* stmt); +void ParserState_deinit(struct ParserState* ps); +void ParserState_beforeIter(struct ParserState* ps); +void ParserState_iterStart(struct ParserState* ps); +void ParserState_iterEnd(struct ParserState* ps); +char* Parser_popToken(Args* buffs_p, char* tokens); + +uint16_t Tokens_getSize(char* tokens) { + if (strEqu("", tokens)) { + return 0; + } + return strCountSign(tokens, 0x1F) + 1; +} + +char* strsPopTokenWithSkip_byStr(Args* outBuffs, + char* stmts, + char* str, + char skipStart, + char skipEnd) { + uint8_t divider_index = 0; + Arg* keeped_arg = arg_setStr(NULL, "", ""); + Arg* poped_arg = arg_setStr(NULL, "", ""); + ParserState_forEachToken(ps, stmts) { + ParserState_iterStart(&ps); + if (ps.branket_deepth == 0) { + if (strEqu(str, ps.token1.pyload)) { + divider_index = ps.iter_index; + } + } + ParserState_iterEnd(&ps); + } + ParserState_deinit(&ps); + ParserState_forEachTokenExistPs(ps, stmts) { + ParserState_iterStart(&ps); + if (ps.iter_index < divider_index) { + poped_arg = arg_strAppend(poped_arg, ps.token1.pyload); + } + if (ps.iter_index > divider_index) { + keeped_arg = arg_strAppend(keeped_arg, ps.token1.pyload); + } + ParserState_iterEnd(&ps); + } + ParserState_deinit(&ps); + char* keeped = arg_getStr(keeped_arg); + char* poped = strsCopy(outBuffs, arg_getStr(poped_arg)); + __platform_memcpy(stmts, keeped, strGetSize(keeped) + 1); + arg_deinit(poped_arg); + arg_deinit(keeped_arg); + return poped; +} + +char* strsGetCleanCmd(Args* outBuffs, char* cmd) { + int32_t size = strGetSize(cmd); + char* strOut = args_getBuff(outBuffs, size); + int32_t iOut = 0; + ParserState_forEachToken(ps, cmd) { + ParserState_iterStart(&ps); + for (uint16_t k = 0; k < strGetSize(ps.token1.pyload); k++) { + strOut[iOut] = ps.token1.pyload[k]; + iOut++; + } + ParserState_iterEnd(&ps); + } + ParserState_deinit(&ps); + /* add \0 */ + strOut[iOut] = 0; + return strOut; +} + +char* strsDeleteBetween(Args* buffs_p, char* strIn, char begin, char end) { + int32_t size = strGetSize(strIn); + char* strOut = args_getBuff(buffs_p, size); + uint8_t deepth = 0; + uint32_t iOut = 0; + for (int i = 0; i < size; i++) { + if (end == strIn[i]) { + deepth--; + } + if (0 == deepth) { + strOut[iOut] = strIn[i]; + iOut++; + } + if (begin == strIn[i]) { + deepth++; + } + } + strOut[iOut] = 0; + return strOut; +} + +static uint8_t Lexer_isError(char* line) { + Args buffs = {0}; + uint8_t res = 0; /* not error */ + char* tokens = Lexer_getTokens(&buffs, line); + if (NULL == tokens) { + res = 1; /* lex error */ + goto exit; + } + goto exit; +exit: + strsDeinit(&buffs); + return res; +} + +static enum StmtType Lexer_matchStmtType(char* right) { + Args buffs = {0}; + enum StmtType stmtType = STMT_none; + char* rightWithoutSubStmt = strsDeleteBetween(&buffs, right, '(', ')'); + rightWithoutSubStmt = + strsDeleteBetween(&buffs, rightWithoutSubStmt, '[', ']'); + + uint8_t is_get_operator = 0; + uint8_t is_get_method = 0; + uint8_t is_get_string = 0; + uint8_t is_get_bytes = 0; + uint8_t is_get_number = 0; + uint8_t is_get_symbol = 0; + uint8_t is_get_index = 0; + ParserState_forEachToken(ps, rightWithoutSubStmt) { + ParserState_iterStart(&ps); + /* collect type */ + if (strEqu(ps.token1.pyload, "[")) { + is_get_index = 1; + goto iter_continue; + } + if (ps.token1.type == TOKEN_operator) { + is_get_operator = 1; + goto iter_continue; + } + if (ps.token2.type == TOKEN_devider) { + is_get_method = 1; + goto iter_continue; + } + if (ps.token1.type == TOKEN_literal) { + if (ps.token1.pyload[0] == '\'' || ps.token1.pyload[0] == '"') { + is_get_string = 1; + goto iter_continue; + } + if (ps.token1.pyload[1] == '\'' || ps.token1.pyload[1] == '"') { + if (ps.token1.pyload[0] == 'b') { + is_get_bytes = 1; + goto iter_continue; + } + } + is_get_number = 1; + goto iter_continue; + } + if (ps.token1.type == TOKEN_symbol) { + is_get_symbol = 1; + goto iter_continue; + } + iter_continue: + ParserState_iterEnd(&ps); + } + if (is_get_operator) { + stmtType = STMT_operator; + goto exit; + } + if (is_get_index) { + stmtType = STMT_list; + goto exit; + } + if (is_get_method) { + stmtType = STMT_method; + goto exit; + } + if (is_get_string) { + stmtType = STMT_string; + goto exit; + } + if (is_get_bytes) { + stmtType = STMT_bytes; + goto exit; + } + if (is_get_number) { + stmtType = STMT_number; + goto exit; + } + if (is_get_symbol) { + stmtType = STMT_reference; + goto exit; + } +exit: + ParserState_deinit(&ps); + strsDeinit(&buffs); + return stmtType; +} + +char* Lexer_printTokens(Args* outBuffs, char* tokens) { + /* init */ + Args buffs = {0}; + char* printOut = strsCopy(&buffs, ""); + + /* process */ + uint16_t token_size = Tokens_getSize(tokens); + for (uint16_t i = 0; i < token_size; i++) { + char* token = Parser_popToken(&buffs, tokens); + if (token[0] == TOKEN_operator) { + printOut = strsAppend(&buffs, printOut, "{opt}"); + printOut = strsAppend(&buffs, printOut, token + 1); + } + if (token[0] == TOKEN_devider) { + printOut = strsAppend(&buffs, printOut, "{dvd}"); + printOut = strsAppend(&buffs, printOut, token + 1); + } + if (token[0] == TOKEN_symbol) { + printOut = strsAppend(&buffs, printOut, "{sym}"); + printOut = strsAppend(&buffs, printOut, token + 1); + } + if (token[0] == TOKEN_literal) { + printOut = strsAppend(&buffs, printOut, "{lit}"); + printOut = strsAppend(&buffs, printOut, token + 1); + } + } + /* out put */ + printOut = strsCopy(outBuffs, printOut); + strsDeinit(&buffs); + return printOut; +} + +uint8_t Parser_checkIsDirect(char* str) { + Args buffs = {0}; + char* tokens = Lexer_getTokens(&buffs, str); + uint8_t res = 0; + if (Parser_isContainToken(tokens, TOKEN_operator, "=")) { + res = 1; + goto exit; + } +exit: + strsDeinit(&buffs); + return res; +} + +Arg* Lexer_setToken(Arg* tokens_arg, + enum TokenType token_type, + char* + operator) { + Args buffs = {0}; + char token_type_buff[3] = {0}; + token_type_buff[0] = 0x1F; + token_type_buff[1] = token_type; + char* tokens = arg_getStr(tokens_arg); + tokens = strsAppend(&buffs, tokens, token_type_buff); + tokens = strsAppend(&buffs, tokens, operator); + Arg* new_tokens_arg = arg_setStr(tokens_arg, "", tokens); + arg_deinit(tokens_arg); + strsDeinit(&buffs); + return new_tokens_arg; +} + +Arg* Lexer_setSymbel(Arg* tokens_arg, + char* stmt, + int32_t i, + int32_t* symbol_start_index) { + Args buffs = {0}; + char* symbol_buff = NULL; + /* nothing to add symbel */ + if (i == *symbol_start_index) { + goto exit; + } + symbol_buff = args_getBuff(&buffs, i - *symbol_start_index); + __platform_memcpy(symbol_buff, stmt + *symbol_start_index, + i - *symbol_start_index); + /* literal */ + if ((symbol_buff[0] == '\'') || (symbol_buff[0] == '"')) { + /* "" or '' */ + tokens_arg = Lexer_setToken(tokens_arg, TOKEN_literal, symbol_buff); + goto exit; + } + + if ((symbol_buff[0] >= '0') && (symbol_buff[0] <= '9')) { + /* number */ + tokens_arg = Lexer_setToken(tokens_arg, TOKEN_literal, symbol_buff); + goto exit; + } + + if ((symbol_buff[0] == 'b') && + ((symbol_buff[1] == '\'') || (symbol_buff[1] == '"'))) { + /* b"" or b'' */ + tokens_arg = Lexer_setToken(tokens_arg, TOKEN_literal, symbol_buff); + goto exit; + } + + /* symbol */ + tokens_arg = Lexer_setToken(tokens_arg, TOKEN_symbol, symbol_buff); + goto exit; +exit: + *symbol_start_index = -1; + strsDeinit(&buffs); + return tokens_arg; +} + +/* tokens is devided by space */ +/* a token is [TOKENTYPE|(CONTENT)] */ +char* Lexer_getTokens(Args* outBuffs, char* stmt) { + /* init */ + Arg* tokens_arg = New_arg(NULL); + tokens_arg = arg_setStr(tokens_arg, "", ""); + int32_t size = strGetSize(stmt); + uint8_t bracket_deepth = 0; + uint8_t c0 = 0; + uint8_t c1 = 0; + uint8_t c2 = 0; + uint8_t c3 = 0; + uint8_t c4 = 0; + uint8_t c5 = 0; + uint8_t c6 = 0; + int32_t symbol_start_index = -1; + int is_in_string = 0; + char* tokens; + + /* process */ + for (int32_t i = 0; i < size; i++) { + /* update char */ + c0 = stmt[i]; + c1 = 0; + c2 = 0; + c3 = 0; + c4 = 0; + c5 = 0; + c6 = 0; + if (i + 1 < size) { + c1 = stmt[i + 1]; + } + if (i + 2 < size) { + c2 = stmt[i + 2]; + } + if (i + 3 < size) { + c3 = stmt[i + 3]; + } + if (i + 4 < size) { + c4 = stmt[i + 4]; + } + if (i + 5 < size) { + c5 = stmt[i + 5]; + } + if (i + 6 < size) { + c6 = stmt[i + 6]; + } + if (-1 == symbol_start_index) { + symbol_start_index = i; + } + + /* solve string */ + if (0 == is_in_string) { + if ('\'' == c0) { + /* in ' */ + is_in_string = 1; + continue; + } + if ('"' == c0) { + /* in "" */ + is_in_string = 2; + continue; + } + } + + if (1 == is_in_string) { + if ('\'' == c0) { + is_in_string = 0; + tokens_arg = Lexer_setSymbel(tokens_arg, stmt, i + 1, + &symbol_start_index); + } + continue; + } + if (2 == is_in_string) { + if ('"' == c0) { + is_in_string = 0; + tokens_arg = Lexer_setSymbel(tokens_arg, stmt, i + 1, + &symbol_start_index); + } + continue; + } + + /* match devider*/ + if (('(' == c0) || (')' == c0) || (',' == c0) || ('[' == c0) || + (']' == c0) || (':' == c0)) { + tokens_arg = + Lexer_setSymbel(tokens_arg, stmt, i, &symbol_start_index); + char content[2] = {0}; + content[0] = c0; + tokens_arg = Lexer_setToken(tokens_arg, TOKEN_devider, content); + if (c0 == '(') { + bracket_deepth++; + } + if (c0 == ')') { + bracket_deepth--; + } + continue; + } + /* match operator */ + if (('>' == c0) || ('<' == c0) || ('*' == c0) || ('/' == c0) || + ('+' == c0) || ('-' == c0) || ('!' == c0) || ('=' == c0) || + ('%' == c0) || ('&' == c0) || ('|' == c0) || ('^' == c0) || + ('~' == c0)) { + if (('*' == c0) || ('/' == c0)) { + /* + =, **=, // + */ + if ((c0 == c1) && ('=' == c2)) { + char content[4] = {0}; + content[0] = c0; + content[1] = c1; + content[2] = '='; + tokens_arg = Lexer_setSymbel(tokens_arg, stmt, i, + &symbol_start_index); + tokens_arg = + Lexer_setToken(tokens_arg, TOKEN_operator, content); + i = i + 2; + continue; + } + } + /* + >>, <<, **, // + */ + if (('>' == c0) || ('<' == c0) || ('*' == c0) || ('/' == c0)) { + if (c0 == c1) { + char content[3] = {0}; + content[0] = c0; + content[1] = c1; + tokens_arg = Lexer_setSymbel(tokens_arg, stmt, i, + &symbol_start_index); + tokens_arg = + Lexer_setToken(tokens_arg, TOKEN_operator, content); + i = i + 1; + continue; + } + } + /* + >=, <=, *=, /=, +=, -=, !=, ==, %= + */ + if (('>' == c0) || ('<' == c0) || ('*' == c0) || ('/' == c0) || + ('+' == c0) || ('-' == c0) || ('!' == c0) || ('=' == c0) || + ('%' == c0)) { + if ('=' == c1) { + char content[3] = {0}; + content[0] = c0; + content[1] = c1; + tokens_arg = Lexer_setSymbel(tokens_arg, stmt, i, + &symbol_start_index); + tokens_arg = + Lexer_setToken(tokens_arg, TOKEN_operator, content); + i = i + 1; + continue; + } + } + + /* single operator */ + /* + +, -, *, ... / + */ + char content[2] = {0}; + content[0] = c0; + tokens_arg = + Lexer_setSymbel(tokens_arg, stmt, i, &symbol_start_index); + tokens_arg = Lexer_setToken(tokens_arg, TOKEN_operator, content); + continue; + } + /* not */ + if ('n' == c0) { + if (('o' == c1) && ('t' == c2) && (' ' == c3)) { + tokens_arg = + Lexer_setSymbel(tokens_arg, stmt, i, &symbol_start_index); + tokens_arg = + Lexer_setToken(tokens_arg, TOKEN_operator, " not "); + i = i + 3; + continue; + } + } + /* and */ + if ('a' == c0) { + if (('n' == c1) && ('d' == c2) && (' ' == c3)) { + tokens_arg = + Lexer_setSymbel(tokens_arg, stmt, i, &symbol_start_index); + tokens_arg = + Lexer_setToken(tokens_arg, TOKEN_operator, " and "); + i = i + 3; + continue; + } + } + /* or */ + if ('o' == c0) { + if (('r' == c1) && (' ' == c2)) { + tokens_arg = + Lexer_setSymbel(tokens_arg, stmt, i, &symbol_start_index); + tokens_arg = Lexer_setToken(tokens_arg, TOKEN_operator, " or "); + i = i + 2; + continue; + } + } + /* as */ + if ('a' == c0) { + if (('s' == c1) && (' ' == c2)) { + tokens_arg = + Lexer_setSymbel(tokens_arg, stmt, i, &symbol_start_index); + tokens_arg = Lexer_setToken(tokens_arg, TOKEN_operator, " as "); + i = i + 2; + continue; + } + } + /* import */ + if ('i' == c0) { + if (('m' == c1) && ('p' == c2) && ('o' == c3) && ('r' == c4) && + ('t' == c5) && (' ' == c6)) { + tokens_arg = + Lexer_setSymbel(tokens_arg, stmt, i, &symbol_start_index); + tokens_arg = + Lexer_setToken(tokens_arg, TOKEN_operator, " import "); + i = i + 5; + continue; + } + } + /* skip spaces */ + if (' ' == c0) { + /* not get symbal */ + if (i == symbol_start_index) { + symbol_start_index++; + } else { + /* already get symbal */ + tokens_arg = + Lexer_setSymbel(tokens_arg, stmt, i, &symbol_start_index); + } + } + if (i == size - 1) { + /* last check symbel */ + tokens_arg = + Lexer_setSymbel(tokens_arg, stmt, size, &symbol_start_index); + } + } + if (0 != bracket_deepth) { + /* bracket match error */ + tokens = NULL; + goto exit; + } + /* output */ + tokens = arg_getStr(tokens_arg); + tokens = strsCopy(outBuffs, tokens); +exit: + arg_deinit(tokens_arg); + return tokens; +} + +char* Parser_popToken(Args* buffs_p, char* tokens) { + return strsPopToken(buffs_p, tokens, 0x1F); +} + +enum TokenType Token_getType(char* token) { + return (enum TokenType)token[0]; +} + +char* Token_getPyload(char* token) { + return (char*)((uintptr_t)token + 1); +} + +uint8_t Parser_isContainToken(char* tokens, + enum TokenType token_type, + char* pyload) { + Args buffs = {0}; + char* tokens_buff = strsCopy(&buffs, tokens); + uint8_t res = 0; + uint16_t token_size = Tokens_getSize(tokens); + for (int i = 0; i < token_size; i++) { + char* token = Parser_popToken(&buffs, tokens_buff); + if (token_type == Token_getType(token)) { + if (strEqu(Token_getPyload(token), pyload)) { + res = 1; + goto exit; + } + } + } +exit: + strsDeinit(&buffs); + return res; +} + +char* Lexer_getOperator(Args* outBuffs, char* stmt) { + Args buffs = {0}; + char* tokens = Lexer_getTokens(&buffs, stmt); + char* operator= NULL; + const char operators[][6] = { + "**", "~", "*", "/", "%", "//", "+", "-", ">>", "<<", + "&", "^", "|", "<", "<=", ">", ">=", "!=", "==", "%=", + "/=", "//=", "-=", "+=", "*=", "**=", " not ", " and ", " or "}; + for (uint32_t i = 0; i < sizeof(operators) / 6; i++) { + if (Parser_isContainToken(tokens, TOKEN_operator, + (char*)operators[i])) { + operator= strsCopy(&buffs, (char*)operators[i]); + } + } + /* match the last operator in equal level */ + if ((strEqu(operator, "+")) || (strEqu(operator, "-"))) { + ParserState_forEachToken(ps, stmt) { + ParserState_iterStart(&ps); + if (strEqu(ps.token1.pyload, "+")) { + operator= strsCopy(&buffs, "+"); + } + if (strEqu(ps.token1.pyload, "-")) { + operator= strsCopy(&buffs, "-"); + } + ParserState_iterEnd(&ps); + } + ParserState_deinit(&ps); + } + /* out put */ + operator= strsCopy(outBuffs, operator); + strsDeinit(&buffs); + return operator; +} + +const char void_str[] = ""; + +void LexToken_update(struct LexToken* lex_token) { + lex_token->type = Token_getType(lex_token->token); + if (lex_token->type == TOKEN_strEnd) { + lex_token->pyload = (char*)void_str; + } else { + lex_token->pyload = Token_getPyload(lex_token->token); + } +} + +void ParserState_iterStart(struct ParserState* ps) { + ps->iter_index++; + ps->iter_buffs = New_strBuff(); + /* token1 is the last token */ + ps->token1.token = strsCopy(ps->iter_buffs, arg_getStr(ps->last_token)); + /* token2 is the next token */ + ps->token2.token = Parser_popToken(ps->iter_buffs, ps->tokens); + /* store last token */ + arg_deinit(ps->last_token); + ps->last_token = arg_setStr(NULL, "", ps->token2.token); + + LexToken_update(&ps->token1); + LexToken_update(&ps->token2); + if (strEqu(ps->token1.pyload, "(")) { + ps->branket_deepth++; + } + if (strEqu(ps->token1.pyload, ")")) { + ps->branket_deepth--; + } + if (strEqu(ps->token1.pyload, "[")) { + ps->branket_deepth++; + } + if (strEqu(ps->token1.pyload, "]")) { + ps->branket_deepth--; + } +} + +void LexToken_init(struct LexToken* lt) { + lt->pyload = NULL; + lt->token = NULL; + lt->type = TOKEN_strEnd; +} + +void ParserState_init(struct ParserState* ps) { + ps->tokens = NULL; + ps->length = 0; + ps->iter_index = 0; + ps->branket_deepth = 0; + ps->last_token = NULL; + ps->iter_buffs = NULL; + ps->buffs_p = New_strBuff(); + LexToken_init(&ps->token1); + LexToken_init(&ps->token2); +} + +void ParserState_iterEnd(struct ParserState* ps) { + args_deinit(ps->iter_buffs); +} + +void ParserState_deinit(struct ParserState* ps) { + if (NULL != ps->last_token) { + arg_deinit(ps->last_token); + } + args_deinit(ps->buffs_p); +} + +void ParserState_parse(struct ParserState* ps, char* stmt) { + ps->tokens = Lexer_getTokens(ps->buffs_p, stmt); + ps->length = Tokens_getSize(ps->tokens); +} + +void ParserState_beforeIter(struct ParserState* ps) { + /* clear first token */ + Parser_popToken(ps->buffs_p, ps->tokens); + ps->last_token = + arg_setStr(NULL, "", Parser_popToken(ps->buffs_p, ps->tokens)); +} + +char* Parser_solveBranckets(Args* outBuffs, + char* content, + char* stmt, + char* mode) { + /* init objects */ + Args buffs = {0}; + Arg* right_arg = arg_setStr(NULL, "", ""); + uint8_t is_in_brancket = 0; + args_setStr(&buffs, "index", ""); + uint8_t matched = 0; + /* exit when NULL */ + if (NULL == content) { + arg_deinit(right_arg); + right_arg = arg_setStr(right_arg, "", stmt); + goto exit; + } + /* exit when not match + (symble|iteral)'[' + */ + ParserState_forEachToken(ps, content) { + ParserState_iterStart(&ps); + if (strEqu(ps.token2.pyload, "[")) { + if (TOKEN_symbol == ps.token1.type || + TOKEN_literal == ps.token1.type) { + matched = 1; + ParserState_iterEnd(&ps); + break; + } + } + ParserState_iterEnd(&ps); + } + ParserState_deinit(&ps); + if (!matched) { + /* not contain '[', return origin */ + arg_deinit(right_arg); + if (strEqu(mode, "right")) { + right_arg = arg_setStr(right_arg, "", content); + } else if (strEqu(mode, "left")) { + right_arg = arg_setStr(right_arg, "", stmt); + } + goto exit; + } + + /* matched [] */ + ParserState_forEachTokenExistPs(ps, content) { + ParserState_iterStart(&ps); + /* found '[' */ + if ((TOKEN_devider == ps.token2.type) && + (strEqu(ps.token2.pyload, "["))) { + /* get 'obj' from obj[] */ + args_setStr(&buffs, "obj", ps.token1.pyload); + is_in_brancket = 1; + /* fond ']' */ + } else if ((TOKEN_devider == ps.token2.type) && + (strEqu(ps.token2.pyload, "]"))) { + is_in_brancket = 0; + char* index = args_getStr(&buffs, "index"); + Arg* index_arg = arg_setStr(NULL, "", index); + index_arg = arg_strAppend(index_arg, ps.token1.pyload); + args_setStr(&buffs, "index", arg_getStr(index_arg)); + arg_deinit(index_arg); + + if (strEqu(mode, "right")) { + right_arg = arg_strAppend(right_arg, "__get__("); + } else if (strEqu(mode, "left")) { + right_arg = arg_strAppend(right_arg, "__set__("); + } + right_arg = arg_strAppend(right_arg, args_getStr(&buffs, "obj")); + right_arg = arg_strAppend(right_arg, ","); + right_arg = arg_strAppend(right_arg, args_getStr(&buffs, "index")); + if (strEqu(mode, "left")) { + right_arg = arg_strAppend(right_arg, ","); + right_arg = arg_strAppend(right_arg, stmt); + right_arg = arg_strAppend(right_arg, + "," + "'"); + right_arg = + arg_strAppend(right_arg, args_getStr(&buffs, "obj")); + right_arg = arg_strAppend(right_arg, "'"); + } + right_arg = arg_strAppend(right_arg, ")"); + args_setStr(&buffs, "index", ""); + /* in brancket and found '[' */ + } else if (is_in_brancket && (!strEqu(ps.token1.pyload, "["))) { + char* index = args_getStr(&buffs, "index"); + Arg* index_arg = arg_setStr(NULL, "", index); + index_arg = arg_strAppend(index_arg, ps.token1.pyload); + args_setStr(&buffs, "index", arg_getStr(index_arg)); + arg_deinit(index_arg); + /* out of brancket and not found ']' */ + } else if (!is_in_brancket && (!strEqu(ps.token1.pyload, "]"))) { + if (TOKEN_strEnd != ps.token1.type) { + right_arg = arg_strAppend(right_arg, ps.token1.pyload); + } + } + ParserState_iterEnd(&ps); + } + ParserState_deinit(&ps); +exit: + /* clean and return */ + content = strsCopy(outBuffs, arg_getStr(right_arg)); + arg_deinit(right_arg); + strsDeinit(&buffs); + return content; +} + +char* Parser_solveRightBranckets(Args* outBuffs, char* right) { + return Parser_solveBranckets(outBuffs, right, NULL, "right"); +} + +char* Parser_solveLeftBranckets(Args* outBuffs, char* right, char* left) { + return Parser_solveBranckets(outBuffs, left, right, "left"); +} + +uint8_t Parser_solveSelfOperator(Args* outbuffs, + char* stmt, + char** right_p, + char** left_p) { + char* left_new = NULL; + char* right_new = NULL; + Arg* left_arg = arg_setStr(NULL, "", ""); + Arg* right_arg = arg_setStr(NULL, "", ""); + Arg* right_arg_new = arg_setStr(NULL, "", ""); + uint8_t is_left_exist = 0; + + Args buffs = {0}; + char _operator[2] = {0}; + char* operator=(char*) _operator; + char* tokens = Lexer_getTokens(&buffs, stmt); + uint8_t is_right = 0; + if (Parser_isContainToken(tokens, TOKEN_operator, "+=")) { + operator[0] = '+'; + } + if (Parser_isContainToken(tokens, TOKEN_operator, "-=")) { + operator[0] = '-'; + } + if (Parser_isContainToken(tokens, TOKEN_operator, "*=")) { + operator[0] = '*'; + } + if (Parser_isContainToken(tokens, TOKEN_operator, "/=")) { + operator[0] = '/'; + } + /* not found self operator */ + if (operator[0] == 0) { + goto exit; + } + /* found self operator */ + is_left_exist = 1; + ParserState_forEachToken(ps, stmt) { + ParserState_iterStart(&ps); + if ((strEqu(ps.token1.pyload, "*=")) || + (strEqu(ps.token1.pyload, "/=")) || + (strEqu(ps.token1.pyload, "+=")) || + (strEqu(ps.token1.pyload, "-="))) { + is_right = 1; + goto iter_continue; + } + if (!is_right) { + left_arg = arg_strAppend(left_arg, ps.token1.pyload); + } else { + right_arg = arg_strAppend(right_arg, ps.token1.pyload); + } + iter_continue: + ParserState_iterEnd(&ps); + } + ParserState_deinit(&ps); + /* connect right */ + right_arg_new = arg_strAppend(right_arg_new, arg_getStr(left_arg)); + right_arg_new = arg_strAppend(right_arg_new, operator); + right_arg_new = arg_strAppend(right_arg_new, "("); + right_arg_new = arg_strAppend(right_arg_new, arg_getStr(right_arg)); + right_arg_new = arg_strAppend(right_arg_new, ")"); + + /* collect left_new and right_new */ + left_new = arg_getStr(left_arg); + right_new = arg_getStr(right_arg_new); + +exit: + strsDeinit(&buffs); + if (NULL != right_new) { + *(right_p) = strsCopy(outbuffs, right_new); + ; + } + if (NULL != left_new) { + *(left_p) = strsCopy(outbuffs, left_new); + } + arg_deinit(right_arg); + arg_deinit(left_arg); + arg_deinit(right_arg_new); + return is_left_exist; +} + +AST* AST_parseStmt(AST* ast, char* stmt) { + Args buffs = {0}; + char* assignment = strsGetFirstToken(&buffs, stmt, '('); + char* method = NULL; + char* ref = NULL; + char* str = NULL; + char* num = NULL; + char* left = NULL; + char* right = NULL; + + right = stmt; + /* solve check direct */ + uint8_t isLeftExist = 0; + if (Parser_checkIsDirect(assignment)) { + isLeftExist = 1; + left = strsCopy(&buffs, ""); + right = strsCopy(&buffs, ""); + uint8_t is_meet_equ = 0; + ParserState_forEachToken(ps, stmt) { + ParserState_iterStart(&ps); + if (strEqu(ps.token1.pyload, "=") && + ps.token1.type == TOKEN_operator) { + is_meet_equ = 1; + ParserState_iterEnd(&ps); + continue; + } + if (0 == is_meet_equ) { + left = strsAppend(&buffs, left, ps.token1.pyload); + } + if (1 == is_meet_equ) { + right = strsAppend(&buffs, right, ps.token1.pyload); + } + ParserState_iterEnd(&ps); + } + ParserState_deinit(&ps); + } + /* solve the += -= /= *= stmt */ + if (!isLeftExist) { + isLeftExist = Parser_solveSelfOperator(&buffs, stmt, &right, &left); + } + + /* solve the [] stmt */ + right = Parser_solveRightBranckets(&buffs, right); + char* right_new = Parser_solveLeftBranckets(&buffs, right, left); + + /* left is contain the '[]' */ + if (!strEqu(right_new, right)) { + /* update new right */ + right = right_new; + /* cancel left */ + isLeftExist = 0; + } + + /* set left */ + if (isLeftExist) { + obj_setStr(ast, (char*)"left", left); + } + /* match statment type */ + enum StmtType stmtType = Lexer_matchStmtType(right); + /* solve operator stmt */ + if (STMT_operator == stmtType) { + char* rightWithoutSubStmt = strsDeleteBetween(&buffs, right, '(', ')'); + char* operator= Lexer_getOperator(&buffs, rightWithoutSubStmt); + obj_setStr(ast, (char*)"operator", operator); + char* rightBuff = strsCopy(&buffs, right); + char* subStmt1 = + strsPopTokenWithSkip_byStr(&buffs, rightBuff, operator, '(', ')'); + char* subStmt2 = rightBuff; + queueObj_pushObj(ast, (char*)"stmt"); + AST_parseStmt(queueObj_getCurrentObj(ast), subStmt1); + queueObj_pushObj(ast, (char*)"stmt"); + AST_parseStmt(queueObj_getCurrentObj(ast), subStmt2); + goto exit; + } + +#if PIKA_BUILTIN_LIST_ENABLE + /* solve list stmt */ + if (STMT_list == stmtType) { + obj_setStr(ast, (char*)"list", "list"); + char* subStmts = strsCut(&buffs, right, '[', ']'); + subStmts = strsAppend(&buffs, subStmts, ","); + Arg* subStmt = arg_setStr(NULL, "", ""); + char* subStmt_str = NULL; + ParserState_forEachToken(ps, subStmts) { + ParserState_iterStart(&ps); + if (ps.branket_deepth > 0) { + /* in brankets */ + /* append token to subStmt */ + subStmt = arg_strAppend(subStmt, ps.token1.pyload); + subStmt_str = arg_getStr(subStmt); + } else { + /* not in brankets */ + if (strEqu(ps.token1.pyload, ",")) { + /* found "," push subStmt */ + queueObj_pushObj(ast, (char*)"stmt"); + subStmt_str = arg_getStr(subStmt); + AST_parseStmt(queueObj_getCurrentObj(ast), subStmt_str); + /* clear subStmt */ + arg_deinit(subStmt); + subStmt = arg_setStr(NULL, "", ""); + } else { + /* not "," append subStmt */ + subStmt = arg_strAppend(subStmt, ps.token1.pyload); + subStmt_str = arg_getStr(subStmt); + } + } + ParserState_iterEnd(&ps); + } + ParserState_deinit(&ps); + arg_deinit(subStmt); + goto exit; + } +#endif + + /* solve method stmt */ + if (STMT_method == stmtType) { + method = strsGetFirstToken(&buffs, right, '('); + obj_setStr(ast, (char*)"method", method); + char* subStmts = strsCut(&buffs, right, '(', ')'); + /* add ',' at the end */ + subStmts = strsAppend(&buffs, subStmts, ","); + /* init process values */ + Arg* subStmt = arg_setStr(NULL, "", ""); + /* start iteration */ + char* subStmt_str = NULL; + ParserState_forEachToken(ps, subStmts) { + ParserState_iterStart(&ps); + /* parse process */ + if (ps.branket_deepth > 0) { + /* in brankets */ + /* append token to subStmt */ + subStmt = arg_strAppend(subStmt, ps.token1.pyload); + subStmt_str = arg_getStr(subStmt); + } else { + /* not in brankets */ + if (strEqu(ps.token1.pyload, ",")) { + /* found "," push subStmt */ + queueObj_pushObj(ast, (char*)"stmt"); + subStmt_str = arg_getStr(subStmt); + AST_parseStmt(queueObj_getCurrentObj(ast), subStmt_str); + /* clear subStmt */ + arg_deinit(subStmt); + subStmt = arg_setStr(NULL, "", ""); + } else { + /* not "," append subStmt */ + subStmt = arg_strAppend(subStmt, ps.token1.pyload); + subStmt_str = arg_getStr(subStmt); + } + } + /* parse preocess end */ + ParserState_iterEnd(&ps); + continue; + } + ParserState_deinit(&ps); + arg_deinit(subStmt); + goto exit; + } + /* solve reference stmt */ + if (STMT_reference == stmtType) { + ref = right; + obj_setStr(ast, (char*)"ref", ref); + goto exit; + } + /* solve str stmt */ + if (STMT_string == stmtType) { + str = right; + str = strsDeleteChar(&buffs, str, '\''); + str = strsDeleteChar(&buffs, str, '\"'); + obj_setStr(ast, (char*)"string", str); + goto exit; + } + /* solve bytes stmt */ + if (STMT_bytes == stmtType) { + str = right + 1; + str = strsDeleteChar(&buffs, str, '\''); + str = strsDeleteChar(&buffs, str, '\"'); + obj_setStr(ast, (char*)"bytes", str); + goto exit; + } + /* solve number stmt */ + if (STMT_number == stmtType) { + num = right; + obj_setStr(ast, (char*)"num", num); + goto exit; + } +exit: + strsDeinit(&buffs); + return ast; +} + +static int32_t Parser_getPyLineBlockDeepth(char* line) { + uint32_t size = strGetSize(line); + for (uint32_t i = 0; i < size; i++) { + if (line[i] != ' ') { + uint32_t spaceNum = i; + if (0 == spaceNum % 4) { + return spaceNum / 4; + } + /* space Num is not 4N, error*/ + return -1; + } + } + return 0; +} + +char* Parser_removeAnnotation(char* line) { + uint8_t is_annotation_exit = 0; + uint8_t is_in_single_quotes = 0; + uint8_t is_in_double_quotes_deepth = 0; + for (uint32_t i = 0; i < strGetSize(line); i++) { + if ('\'' == line[i]) { + is_in_single_quotes = !is_in_single_quotes; + continue; + } + if ('"' == line[i]) { + is_in_double_quotes_deepth = !is_in_double_quotes_deepth; + continue; + } + if (!(is_in_single_quotes == 0 && is_in_double_quotes_deepth == 0)) { + continue; + } + if ('#' == line[i]) { + /* end the line */ + line[i] = 0; + is_annotation_exit = 1; + break; + } + } + /* no annotation, exit */ + if (!is_annotation_exit) { + return line; + } + /* check empty line */ + for (uint32_t i = 0; i < strGetSize(line); i++) { + if (' ' != line[i]) { + return line; + } + } + /* is an emply line */ + line = "@annontation"; + return line; +} + +/* match block start keywords */ +const char control_keywords[][9] = {"break", "continue"}; + +/* normal keyward */ +const char normal_keywords[][7] = {"while", "if", "elif"}; + +AST* AST_parseLine(char* line, Stack* block_stack) { + /* line is not exist */ + if (line == NULL) { + return NULL; + } + /* init data */ + AST* ast = New_queueObj(); + Args buffs = {0}; + int8_t block_deepth_now, block_deepth_last = -1; + char *line_start, *stmt; + /* get block deepth */ + block_deepth_now = Parser_getPyLineBlockDeepth(line); + /* set block deepth */ + if (block_deepth_now == -1) { + /* get block_deepth error */ + __platform_printf( + "IndentationError: unexpected indent, only support 4 spaces\r\n"); + obj_deinit(ast); + ast = NULL; + goto exit; + } + obj_setInt(ast, "blockDeepth", block_deepth_now); + + /* check if exit block */ + if (NULL != block_stack) { + block_deepth_last = stack_getTop(block_stack); + /* exit each block */ + for (int i = 0; i < block_deepth_last - block_deepth_now; i++) { + QueueObj* exit_block_queue = obj_getObj(ast, "exitBlock", 0); + /* create an exit_block queue */ + if (NULL == exit_block_queue) { + obj_newObj(ast, "exitBlock", "", New_TinyObj); + exit_block_queue = obj_getObj(ast, "exitBlock", 0); + queueObj_init(exit_block_queue); + } + char buff[10] = {0}; + char* block_type = stack_popStr(block_stack, buff); + /* push exit block type to exit_block queue */ + queueObj_pushStr(exit_block_queue, block_type); + } + } + + line_start = line + block_deepth_now * 4; + stmt = line_start; + + // "while" "if" "elif" + for (uint32_t i = 0; i < sizeof(normal_keywords) / 7; i++) { + char* keyword = (char*)normal_keywords[i]; + uint8_t keyword_len = strGetSize(keyword); + if (strIsStartWith(line_start, keyword) && + (line_start[keyword_len] == ' ')) { + stmt = strsCut(&buffs, line_start, ' ', ':'); + obj_setStr(ast, "block", keyword); + if (NULL != block_stack) { + stack_pushStr(block_stack, keyword); + } + goto block_matched; + } + } + + /* contral keyward */ + /* "break", "continue" */ + for (uint32_t i = 0; i < sizeof(control_keywords) / 8; i++) { + char* keyward = (char*)control_keywords[i]; + uint8_t keyward_size = strGetSize(keyward); + if ((strIsStartWith(line_start, keyward)) && + ((line_start[keyward_size] == ' ') || + (line_start[keyward_size] == 0))) { + obj_setStr(ast, keyward, ""); + stmt = ""; + goto block_matched; + } + } + + /* for */ + if (strIsStartWith(line_start, "for ")) { + Args* list_buffs = New_strBuff(); + char* line_buff = strsCopy(list_buffs, line_start + 4); + char* arg_in = strsPopToken(list_buffs, line_buff, ' '); + obj_setStr(ast, "arg_in", arg_in); + strsPopToken(list_buffs, line_buff, ' '); + if (strIsStartWith(line_buff, "range(")) { + obj_setInt(ast, "isRange", 1); + } + char* list_in = strsPopToken(list_buffs, line_buff, ':'); + list_in = strsAppend(list_buffs, "iter(", list_in); + list_in = strsAppend(list_buffs, list_in, ")"); + list_in = strsCopy(&buffs, list_in); + args_deinit(list_buffs); + obj_setStr(ast, "block", "for"); + obj_setStr(ast, "list_in", list_in); + if (NULL != block_stack) { + stack_pushStr(block_stack, "for"); + } + stmt = list_in; + goto block_matched; + } + + /* else */ + if (strIsStartWith(line_start, "else")) { + if ((line_start[4] == ' ') || (line_start[4] == ':')) { + stmt = ""; + obj_setStr(ast, "block", "else"); + if (NULL != block_stack) { + stack_pushStr(block_stack, "else"); + } + } + goto block_matched; + } + if (strEqu(line_start, "return")) { + obj_setStr(ast, "return", ""); + stmt = ""; + goto block_matched; + } + if (strIsStartWith(line_start, "return ")) { + char* lineBuff = strsCopy(&buffs, line_start); + strsPopToken(&buffs, lineBuff, ' '); + stmt = lineBuff; + obj_setStr(ast, "return", ""); + goto block_matched; + } + if (strIsStartWith(line_start, "global ")) { + stmt = ""; + char* global_list = line_start + 7; + global_list = strsGetCleanCmd(&buffs, global_list); + obj_setStr(ast, "global", global_list); + goto block_matched; + } + if (strIsStartWith(line_start, (char*)"def ")) { + stmt = ""; + char* declear = strsCut(&buffs, line_start, ' ', ':'); + declear = strsGetCleanCmd(&buffs, declear); + obj_setStr(ast, "block", "def"); + obj_setStr(ast, "declear", declear); + if (NULL != block_stack) { + stack_pushStr(block_stack, "def"); + } + goto block_matched; + } + if (strIsStartWith(line_start, (char*)"class ")) { + stmt = ""; + char* declear = strsCut(&buffs, line_start, ' ', ':'); + declear = strsGetCleanCmd(&buffs, declear); + obj_setStr(ast, "block", "class"); + obj_setStr(ast, "declear", declear); + if (NULL != block_stack) { + stack_pushStr(block_stack, "class"); + } + goto block_matched; + } + +block_matched: + stmt = strsGetCleanCmd(&buffs, stmt); + ast = AST_parseStmt(ast, stmt); + goto exit; +exit: + strsDeinit(&buffs); + return ast; +} + +static char* Parser_PreProcess_import(Args* buffs_p, char* line) { + Args buffs = {0}; + char* line_out = line; + char* alias = NULL; + char* origin = NULL; + char* stmt = line + 7; + if (!strIsStartWith(line, "import ")) { + line_out = line; + goto exit; + } + + ParserState_forEachToken(ps, stmt) { + ParserState_iterStart(&ps); + if (strEqu(ps.token2.pyload, " as ")) { + origin = strsCopy(&buffs, ps.token1.pyload); + } + if (strEqu(ps.token1.pyload, " as ")) { + alias = strsCopy(&buffs, ps.token2.pyload); + } + ParserState_iterEnd(&ps); + } + ParserState_deinit(&ps); + + if (NULL == alias) { + line_out = strsCopy(buffs_p, ""); + goto exit; + } + + if (NULL == origin) { + line_out = strsCopy(buffs_p, ""); + goto exit; + } + + line_out = + strsFormat(&buffs, PIKA_LINE_BUFF_SIZE, "%s = %s", alias, origin); + line_out = strsCopy(buffs_p, line_out); +exit: + strsDeinit(&buffs); + return line_out; +} + +static char* Parser_PreProcess_from(Args* buffs_p, char* line) { + Args buffs = {0}; + char* line_out = line; + char* class = NULL; + char* module = NULL; + char* alias = NULL; + char* stmt = line + 5; + if (!strIsStartWith(line, "from ")) { + line_out = line; + goto exit; + } + + ParserState_forEachToken(ps, stmt) { + ParserState_iterStart(&ps); + if (strEqu(ps.token2.pyload, " import ")) { + module = strsCopy(&buffs, ps.token1.pyload); + } + if (strEqu(ps.token1.pyload, " import ")) { + class = strsCopy(&buffs, ps.token2.pyload); + } + if (strEqu(ps.token1.pyload, " as ")) { + alias = strsCopy(&buffs, ps.token2.pyload); + } + ParserState_iterEnd(&ps); + } + ParserState_deinit(&ps); + + if (NULL == module) { + line_out = strsCopy(buffs_p, ""); + goto exit; + } + + if (NULL == class) { + line_out = strsCopy(buffs_p, ""); + goto exit; + } + + if (NULL == alias) { + alias = class; + } + + line_out = strsFormat(&buffs, PIKA_LINE_BUFF_SIZE, "%s = %s.%s", alias, + module, class); + line_out = strsCopy(buffs_p, line_out); +exit: + strsDeinit(&buffs); + return line_out; +} + +static char* Parser_linePreProcess(Args* buffs_p, char* line) { + /* check syntex error */ + if (Lexer_isError(line)) { + line = NULL; + goto exit; + } + /* process EOL */ + line = strsDeleteChar(buffs_p, line, '\r'); + line = Parser_removeAnnotation(line); + line = Parser_PreProcess_import(buffs_p, line); + line = Parser_PreProcess_from(buffs_p, line); +exit: + return line; +} + +char* Parser_LineToAsm(Args* buffs_p, char* line, Stack* blockStack) { + char* ASM = NULL; + AST* ast = NULL; + /* pre process */ + line = Parser_linePreProcess(buffs_p, line); + if (NULL == line) { + /* preprocess error */ + goto exit; + } + if (strEqu("@annontation", line)) { + ASM = ""; + goto exit; + } + + /* parse line to tokens */ + /* parse tokens to AST */ + ast = AST_parseLine(line, blockStack); + /* gen ASM from AST */ + ASM = AST_toPikaASM(ast, buffs_p); +exit: + if (NULL != ast) { + AST_deinit(ast); + } + return ASM; +} + +static int Parser_isVoidLine(char* line) { + for (uint32_t i = 0; i < strGetSize(line); i++) { + if (line[i] != ' ') { + return 0; + } + } + return 1; +} + +static uint8_t Parser_checkIsMultiComment(char* line) { + for (uint32_t i = 0; i < strGetSize(line); i++) { + /* not match ' or " */ + if ((line[i] != '\'') && (line[i] != '"')) { + continue; + } + /* not match ''' or """ */ + if (!((line[i + 1] == line[i]) && (line[i + 2] == line[i]))) { + continue; + } + /* check char befor the ''' or """ */ + if (!((0 == i) || (line[i - 1] == ' '))) { + continue; + } + /* check char after the ''' or """ */ + if (!((line[i + 3] == ' ') || (line[i + 3] == 0))) { + continue; + } + /* mached */ + return 1; + } + /* not mached */ + return 0; +} + +static char* Parser_parsePyLines(Args* outBuffs, + ByteCodeFrame* bytecode_frame, + char* py_lines) { + Stack block_stack; + stack_init(&block_stack); + Arg* asm_buff = arg_setStr(NULL, "", ""); + uint32_t lines_offset = 0; + uint32_t lines_size = strGetSize(py_lines); + uint16_t lines_num = strCountSign(py_lines, '\n'); + uint16_t lines_index = 0; + uint8_t is_in_multi_comment = 0; + char* out_ASM = NULL; + char* single_ASM; + uint32_t line_size = 0; + /* parse each line */ + while (1) { + lines_index++; + Args buffs = {0}; + /* get single line by pop multiline */ + char* line = strsGetFirstToken(&buffs, py_lines + lines_offset, '\n'); + /* filter for not end \n */ + if (lines_index != lines_num) { + if (Parser_isVoidLine(line)) { + goto next_line; + } + } + + /* filter for multiline comment ''' or """ */ + if (Parser_checkIsMultiComment(line)) { + is_in_multi_comment = ~is_in_multi_comment; + goto next_line; + } + + /* skipe multiline comment */ + if (is_in_multi_comment) { + goto next_line; + } + + /* parse single Line to Asm */ + single_ASM = Parser_LineToAsm(&buffs, line, &block_stack); + if (NULL == single_ASM) { + out_ASM = NULL; + strsDeinit(&buffs); + goto exit; + } + if (NULL == bytecode_frame) { + /* store ASM */ + asm_buff = arg_strAppend(asm_buff, single_ASM); + } else if (NULL == outBuffs) { + /* store ByteCode */ + byteCodeFrame_appendFromAsm(bytecode_frame, single_ASM); + } + next_line: + line_size = strGetSize(line); + lines_offset = lines_offset + line_size + 1; + strsDeinit(&buffs); + /* exit when finished */ + if (lines_offset >= lines_size) { + break; + } + } + if (NULL != outBuffs) { + /* load stored ASM */ + out_ASM = strsCopy(outBuffs, arg_getStr(asm_buff)); + } else { + out_ASM = (char*)1; + } + goto exit; +exit: + if (NULL != asm_buff) { + arg_deinit(asm_buff); + } + stack_deinit(&block_stack); + return out_ASM; +}; + +int bytecodeFrame_fromMultiLine(ByteCodeFrame* bytecode_frame, + char* multi_line) { + if (NULL == Parser_parsePyLines(NULL, bytecode_frame, multi_line)) { + /* error */ + return 1; + } + /* succeed */ + return 0; +}; + +char* Parser_multiLineToAsm(Args* outBuffs, char* multi_line) { + return Parser_parsePyLines(outBuffs, NULL, multi_line); +} + +char* AST_appandPikaASM(AST* ast, AST* subAst, Args* outBuffs, char* pikaAsm) { + int deepth = obj_getInt(ast, "deepth"); + Args buffs = {0}; + while (1) { + QueueObj* subStmt = queueObj_popObj(subAst); + if (NULL == subStmt) { + break; + } + obj_setInt(ast, "deepth", deepth + 1); + pikaAsm = AST_appandPikaASM(ast, subStmt, &buffs, pikaAsm); + } + char* method = obj_getStr(subAst, "method"); + char* list = obj_getStr(subAst, "list"); + char* operator= obj_getStr(subAst, "operator"); + char* ref = obj_getStr(subAst, "ref"); + char* left = obj_getStr(subAst, "left"); + char* str = obj_getStr(subAst, "string"); + char* bytes = obj_getStr(subAst, "bytes"); + char* num = obj_getStr(subAst, "num"); + char* buff = args_getBuff(&buffs, PIKA_SPRINTF_BUFF_SIZE); + if (NULL != list) { + __platform_sprintf(buff, "%d LST \n", deepth); + pikaAsm = strsAppend(&buffs, pikaAsm, buff); + } + if (NULL != ref) { + __platform_sprintf(buff, "%d REF %s\n", deepth, ref); + pikaAsm = strsAppend(&buffs, pikaAsm, buff); + } + if (NULL != operator) { + __platform_sprintf(buff, "%d OPT %s\n", deepth, operator); + pikaAsm = strsAppend(&buffs, pikaAsm, buff); + } + if (NULL != method) { + __platform_sprintf(buff, "%d RUN %s\n", deepth, method); + pikaAsm = strsAppend(&buffs, pikaAsm, buff); + } + if (NULL != str) { + __platform_sprintf(buff, "%d STR %s\n", deepth, str); + pikaAsm = strsAppend(&buffs, pikaAsm, buff); + } + if (NULL != bytes) { + __platform_sprintf(buff, "%d BYT %s\n", deepth, bytes); + pikaAsm = strsAppend(&buffs, pikaAsm, buff); + } + if (NULL != num) { + __platform_sprintf(buff, "%d NUM %s\n", deepth, num); + pikaAsm = strsAppend(&buffs, pikaAsm, buff); + } + if (NULL != left) { + __platform_sprintf(buff, "%d OUT %s\n", deepth, left); + pikaAsm = strsAppend(&buffs, pikaAsm, buff); + } + obj_setInt(ast, "deepth", deepth - 1); + goto exit; +exit: + pikaAsm = strsCopy(outBuffs, pikaAsm); + strsDeinit(&buffs); + return pikaAsm; +} + +char* ASM_addBlockDeepth(AST* ast, + Args* buffs_p, + char* pikaAsm, + uint8_t deepthOffset) { + pikaAsm = strsAppend(buffs_p, pikaAsm, (char*)"B"); + char buff[11]; + pikaAsm = strsAppend( + buffs_p, pikaAsm, + fast_itoa(buff, obj_getInt(ast, "blockDeepth") + deepthOffset)); + pikaAsm = strsAppend(buffs_p, pikaAsm, (char*)"\n"); + return pikaAsm; +} + +char* AST_toPikaASM(AST* ast, Args* outBuffs) { + Args buffs = {0}; + char* pikaAsm = strsCopy(&buffs, ""); + QueueObj* exitBlock; + uint8_t is_block_matched; + if (NULL == ast) { + pikaAsm = NULL; + goto exit; + } + exitBlock = obj_getObj(ast, "exitBlock", 0); + /* exiting from block */ + if (exitBlock != NULL) { + while (1) { + uint8_t block_type_num = obj_getInt(exitBlock, "top") - + obj_getInt(exitBlock, "bottom") - 1; + char* block_type = queueObj_popStr(exitBlock); + if (NULL == block_type) { + break; + } + /* goto the while start when exit while block */ + if (strEqu(block_type, "while")) { + pikaAsm = + ASM_addBlockDeepth(ast, outBuffs, pikaAsm, block_type_num); + pikaAsm = strsAppend(outBuffs, pikaAsm, (char*)"0 JMP -1\n"); + } + /* goto the while start when exit while block */ + if (strEqu(block_type, "for")) { + pikaAsm = + ASM_addBlockDeepth(ast, outBuffs, pikaAsm, block_type_num); + pikaAsm = strsAppend(outBuffs, pikaAsm, (char*)"0 JMP -1\n"); + /* garbage collect for the list */ + pikaAsm = + ASM_addBlockDeepth(ast, outBuffs, pikaAsm, block_type_num); + char _l_x[] = "_lx"; + char block_deepth_char = + obj_getInt(ast, "blockDeepth") + block_type_num + '0'; + _l_x[sizeof(_l_x) - 2] = block_deepth_char; + pikaAsm = strsAppend(outBuffs, pikaAsm, (char*)"0 DEL "); + pikaAsm = strsAppend(outBuffs, pikaAsm, (char*)_l_x); + pikaAsm = strsAppend(outBuffs, pikaAsm, (char*)"\n"); + } + /* return when exit method */ + if (strEqu(block_type, "def")) { + pikaAsm = ASM_addBlockDeepth(ast, outBuffs, pikaAsm, + block_type_num + 1); + pikaAsm = strsAppend(outBuffs, pikaAsm, (char*)"0 RET \n"); + } + /* return when exit class */ + if (strEqu(block_type, "class")) { + pikaAsm = ASM_addBlockDeepth(ast, outBuffs, pikaAsm, + block_type_num + 1); + pikaAsm = + strsAppend(outBuffs, pikaAsm, (char*)"0 RAS $origin\n"); + pikaAsm = ASM_addBlockDeepth(ast, outBuffs, pikaAsm, 1); + pikaAsm = strsAppend(outBuffs, pikaAsm, (char*)"0 NEW self\n"); + pikaAsm = strsAppend(outBuffs, pikaAsm, (char*)"0 RET \n"); + } + } + } + /* add block deepth */ + /* example: B0 */ + pikaAsm = ASM_addBlockDeepth(ast, outBuffs, pikaAsm, 0); + + /* "deepth" is invoke deepth, not the blockDeepth */ + obj_setInt(ast, "deepth", 0); + + /* match block */ + is_block_matched = 0; + if (strEqu(obj_getStr(ast, "block"), "for")) { + /* for "for" iter */ + char* arg_in = obj_getStr(ast, "arg_in"); + Arg* newAsm_arg = arg_setStr(NULL, "", ""); + char _l_x[] = "_lx"; + char block_deepth_char = '0'; + block_deepth_char += obj_getInt(ast, "blockDeepth"); + _l_x[sizeof(_l_x) - 2] = block_deepth_char; + /* init iter */ + /* get the iter(_l) */ + pikaAsm = AST_appandPikaASM(ast, ast, &buffs, pikaAsm); + newAsm_arg = arg_strAppend(newAsm_arg, "0 OUT "); + newAsm_arg = arg_strAppend(newAsm_arg, _l_x); + newAsm_arg = arg_strAppend(newAsm_arg, "\n"); + if (1 == obj_getInt(ast, "isRange")) { + newAsm_arg = arg_strAppend(newAsm_arg, + "0 REF _r1\n" + "0 REF _r2\n" + "0 OUT "); + newAsm_arg = arg_strAppend(newAsm_arg, _l_x); + newAsm_arg = arg_strAppend(newAsm_arg, + ".a2\n" + "0 OUT "); + newAsm_arg = arg_strAppend(newAsm_arg, _l_x); + newAsm_arg = arg_strAppend(newAsm_arg, ".a1\n"); + } + pikaAsm = strsAppend(&buffs, pikaAsm, arg_getStr(newAsm_arg)); + arg_deinit(newAsm_arg); + newAsm_arg = arg_setStr(NULL, "", ""); + /* get next */ + /* run next(_l) */ + /* check item is exist */ + pikaAsm = ASM_addBlockDeepth(ast, outBuffs, pikaAsm, 0); + newAsm_arg = arg_strAppend(newAsm_arg, "0 RUN "); + newAsm_arg = arg_strAppend(newAsm_arg, _l_x); + newAsm_arg = arg_strAppend(newAsm_arg, + ".__next__\n" + "0 OUT "); + newAsm_arg = arg_strAppend(newAsm_arg, arg_in); + newAsm_arg = arg_strAppend(newAsm_arg, + "\n" + "0 EST "); + newAsm_arg = arg_strAppend(newAsm_arg, arg_in); + newAsm_arg = arg_strAppend(newAsm_arg, "\n0 JEZ 2\n"); + pikaAsm = strsAppend(&buffs, pikaAsm, arg_getStr(newAsm_arg)); + arg_deinit(newAsm_arg); + is_block_matched = 1; + goto exit; + } + if (strEqu(obj_getStr(ast, "block"), "while")) { + /* parse stmt ast */ + pikaAsm = AST_appandPikaASM(ast, ast, &buffs, pikaAsm); + pikaAsm = strsAppend(&buffs, pikaAsm, "0 JEZ 2\n"); + is_block_matched = 1; + goto exit; + } + if (strEqu(obj_getStr(ast, "block"), "if")) { + /* parse stmt ast */ + pikaAsm = AST_appandPikaASM(ast, ast, &buffs, pikaAsm); + pikaAsm = strsAppend(&buffs, pikaAsm, "0 JEZ 1\n"); + is_block_matched = 1; + goto exit; + } + if (strEqu(obj_getStr(ast, "block"), "else")) { + pikaAsm = strsAppend(&buffs, pikaAsm, "0 NEL 1\n"); + goto exit; + } + if (strEqu(obj_getStr(ast, "block"), "elif")) { + /* skip if __else is 0 */ + pikaAsm = strsAppend(&buffs, pikaAsm, "0 NEL 1\n"); + /* parse stmt ast */ + pikaAsm = AST_appandPikaASM(ast, ast, &buffs, pikaAsm); + /* skip if stmt is 0 */ + pikaAsm = strsAppend(&buffs, pikaAsm, "0 JEZ 1\n"); + is_block_matched = 1; + goto exit; + } + if (strEqu(obj_getStr(ast, "block"), "def")) { + pikaAsm = strsAppend(&buffs, pikaAsm, "0 DEF "); + pikaAsm = strsAppend(&buffs, pikaAsm, obj_getStr(ast, "declear")); + pikaAsm = strsAppend(&buffs, pikaAsm, + "\n" + "0 JMP 1\n"); + is_block_matched = 1; + goto exit; + } + + if (strEqu(obj_getStr(ast, "block"), "class")) { + char* declear = obj_getStr(ast, "declear"); + char* thisClass = NULL; + char* superClass = NULL; + if (strIsContain(declear, '(')) { + thisClass = strsGetFirstToken(&buffs, declear, '('); + superClass = strsCut(&buffs, declear, '(', ')'); + } else { + thisClass = declear; + superClass = ""; + } + if (strEqu("", superClass)) { + /* default superClass */ + superClass = "PikaStdLib.PikaObj"; + } + if (strEqu("TinyObj", superClass)) { + /* default superClass */ + superClass = "PikaStdLib.PikaObj"; + } + pikaAsm = strsAppend(&buffs, pikaAsm, "0 CLS "); + pikaAsm = strsAppend(&buffs, pikaAsm, + strsAppend(&buffs, thisClass, + "()\n" + "0 JMP 1\n")); + char block_deepth_str[] = "B0\n"; + /* goto deeper block */ + block_deepth_str[1] += obj_getInt(ast, "blockDeepth") + 1; + pikaAsm = strsAppend(&buffs, pikaAsm, block_deepth_str); + pikaAsm = strsAppend(&buffs, pikaAsm, "0 RUN "); + pikaAsm = strsAppend(&buffs, pikaAsm, superClass); + pikaAsm = strsAppend(&buffs, pikaAsm, "\n"); + pikaAsm = strsAppend(&buffs, pikaAsm, "0 OUT self\n"); + pikaAsm = strsAppend(&buffs, pikaAsm, block_deepth_str); + pikaAsm = strsAppend(&buffs, pikaAsm, "0 RAS self\n"); + is_block_matched = 1; + goto exit; + } + + if (obj_isArgExist(ast, "return")) { + /* parse stmt ast */ + pikaAsm = AST_appandPikaASM(ast, ast, &buffs, pikaAsm); + pikaAsm = strsAppend(&buffs, pikaAsm, "0 RET \n"); + is_block_matched = 1; + goto exit; + } + if (obj_isArgExist(ast, "global")) { + /* parse stmt ast */ + pikaAsm = AST_appandPikaASM(ast, ast, &buffs, pikaAsm); + pikaAsm = strsAppend(&buffs, pikaAsm, "0 GLB "); + pikaAsm = strsAppend(&buffs, pikaAsm, obj_getStr(ast, "global")); + pikaAsm = strsAppend(&buffs, pikaAsm, "\n"); + is_block_matched = 1; + goto exit; + } + if (obj_isArgExist(ast, "break")) { + /* parse stmt ast */ + pikaAsm = AST_appandPikaASM(ast, ast, &buffs, pikaAsm); + pikaAsm = strsAppend(&buffs, pikaAsm, "0 BRK\n"); + is_block_matched = 1; + goto exit; + } + if (obj_isArgExist(ast, "continue")) { + /* parse stmt ast */ + pikaAsm = AST_appandPikaASM(ast, ast, &buffs, pikaAsm); + pikaAsm = strsAppend(&buffs, pikaAsm, "0 CTN\n"); + is_block_matched = 1; + goto exit; + } +exit: + if (NULL == pikaAsm) { + strsDeinit(&buffs); + return NULL; + } + if (!is_block_matched) { + /* parse stmt ast */ + pikaAsm = AST_appandPikaASM(ast, ast, &buffs, pikaAsm); + } + + /* output pikaAsm */ + pikaAsm = strsCopy(outBuffs, pikaAsm); + strsDeinit(&buffs); + return pikaAsm; +} + +int32_t AST_deinit(AST* ast) { + return obj_deinit(ast); +} + +ByteCodeFrame* byteCodeFrame_appendFromAsm(ByteCodeFrame* self, char* pikaAsm) { + Asmer asmer = { + .asm_code = pikaAsm, + .block_deepth_now = 0, + .is_new_line = 0, + .line_pointer = pikaAsm, + }; + uint16_t const_pool_offset; + char* data; + uint16_t exist_offset; + + char line_buff[PIKA_PATH_BUFF_SIZE] = {0}; + for (int i = 0; i < strCountSign(pikaAsm, '\n'); i++) { + char* line = strGetLine(line_buff, asmer.line_pointer); + InstructUnit ins_unit = {0}; + /* remove '\r' */ + if (line[strGetSize(line) - 1] == '\r') { + line[strGetSize(line) - 1] = 0; + } + /* process block deepth flag*/ + if ('B' == line[0]) { + asmer.block_deepth_now = line[1] - '0'; + asmer.is_new_line = 1; + goto next_line; + } + + /* process each ins */ + + /* get constPool offset */ + const_pool_offset = 0; + + data = line + 6; + exist_offset = constPool_getOffsetByData(&(self->const_pool), data); + + /* get const offset */ + if (strEqu(data, "")) { + /* not need const value */ + const_pool_offset = 0; + } else if (65535 == exist_offset) { + /* push new const value */ + const_pool_offset = constPool_getLastOffset(&(self->const_pool)); + /* load const to const pool buff */ + constPool_append(&(self->const_pool), data); + } else { + /* use exist const value */ + const_pool_offset = exist_offset; + } + + /* load Asm to byte code unit */ + instructUnit_setBlockDeepth(&ins_unit, asmer.block_deepth_now); + instructUnit_setInvokeDeepth(&ins_unit, line[0] - '0'); + instructUnit_setConstPoolIndex(&ins_unit, const_pool_offset); + instructUnit_setInstruct(&ins_unit, pikaVM_getInstructFromAsm(line)); + if (asmer.is_new_line) { + instructUnit_setIsNewLine(&ins_unit, 1); + asmer.is_new_line = 0; + } + + /* append instructUnit to instructArray */ + instructArray_append(&(self->instruct_array), &ins_unit); + + next_line: + /* point to next line */ + asmer.line_pointer += strGetLineSize(asmer.line_pointer) + 1; + } + return self; +} + +char* Parser_byteCodeToAsm(Args* outBuffs, char* pikaByteCode) { + return NULL; +} + +void Parser_compilePyToBytecodeArray(char* lines) { + ByteCodeFrame bytecode_frame; + byteCodeFrame_init(&bytecode_frame); + bytecodeFrame_fromMultiLine(&bytecode_frame, lines); + /* do something */ + byteCodeFrame_print(&bytecode_frame); + byteCodeFrame_printAsArray(&bytecode_frame); + /* deinit */ + byteCodeFrame_deinit(&bytecode_frame); +} + +/* const Pool output redirect */ +static void __handler_constPool_output_file(ConstPool* self, char* content) { + /* to ram */ + uint16_t size = strGetSize(content) + 1; + self->arg_buff = arg_append(self->arg_buff, content, size); + /* to flash */ + __platform_fwrite(content, 1, size, self->output_f); +} + +/* instruct array output redirect */ +static void __handler_instructArray_output_none(InstructArray* self, + InstructUnit* ins_unit) { + /* none */ +} + +static void __handler_instructArray_output_file(InstructArray* self, + InstructUnit* ins_unit) { + /* to flash */ + __platform_fwrite(ins_unit, 1, instructUnit_getSize(), self->output_f); +} + +/* + need implament : + __platform_fopen() + __platform_fwrite() + __platform_fclose() +*/ +int pikaCompile(char* output_file_name, char* py_lines) { + ByteCodeFrame bytecode_frame = {0}; + + FILE* bytecode_f = __platform_fopen(output_file_name, "w+"); + /* main process */ + + /* step 1, get size of const pool and instruct array */ + byteCodeFrame_init(&bytecode_frame); + bytecode_frame.const_pool.output_f = bytecode_f; + bytecode_frame.instruct_array.output_f = bytecode_f; + bytecode_frame.instruct_array.output_redirect_fun = + __handler_instructArray_output_none; + Parser_parsePyLines(NULL, &bytecode_frame, py_lines); + uint16_t const_pool_size = bytecode_frame.const_pool.size; + uint16_t instruct_array_size = bytecode_frame.instruct_array.size; + byteCodeFrame_deinit(&bytecode_frame); + + /* step 2, write instruct array to file */ + __platform_fwrite(&instruct_array_size, 1, 2, bytecode_f); + byteCodeFrame_init(&bytecode_frame); + bytecode_frame.const_pool.output_f = bytecode_f; + bytecode_frame.instruct_array.output_f = bytecode_f; + /* instruct array to file */ + bytecode_frame.instruct_array.output_redirect_fun = + __handler_instructArray_output_file; + Parser_parsePyLines(NULL, &bytecode_frame, py_lines); + byteCodeFrame_deinit(&bytecode_frame); + + /* step 3, write const pool to file */ + __platform_fwrite(&const_pool_size, 1, 2, bytecode_f); + char void_ = 0; + /* add \0 at the start */ + __platform_fwrite(&void_, 1, 1, bytecode_f); + byteCodeFrame_init(&bytecode_frame); + bytecode_frame.const_pool.output_f = bytecode_f; + bytecode_frame.instruct_array.output_f = bytecode_f; + /* const pool to file */ + bytecode_frame.const_pool.output_redirect_fun = + __handler_constPool_output_file; + /* instruct array to none */ + bytecode_frame.instruct_array.output_redirect_fun = + __handler_instructArray_output_none; + Parser_parsePyLines(NULL, &bytecode_frame, py_lines); + byteCodeFrame_deinit(&bytecode_frame); + + /* deinit */ + __platform_fclose(bytecode_f); + /* succeed */ + return 0; +}; diff --git a/port/linux/package/pikascript/pikascript-core/PikaParser.h b/port/linux/package/pikascript/pikascript-core/PikaParser.h new file mode 100644 index 000000000..a18636054 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/PikaParser.h @@ -0,0 +1,100 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __PIKA_PARSER__H +#define __PIKA_PARSER__H +#include "PikaVM.h" +#include "dataQueueObj.h" +#include "dataStack.h" + +enum TokenType { + TOKEN_strEnd = 0, + TOKEN_symbol, + TOKEN_keyword, + TOKEN_operator, + TOKEN_devider, + TOKEN_literal, +}; + +enum StmtType { + STMT_reference, + STMT_string, + STMT_bytes, + STMT_number, + STMT_method, + STMT_operator, + STMT_list, + STMT_none, +}; + +typedef struct Asmer_t { + char* asm_code; + uint8_t block_deepth_now; + uint8_t is_new_line; + char* line_pointer; +} Asmer; + +struct LexToken { + char* token; + enum TokenType type; + char* pyload; +}; + +struct ParserState { + char* tokens; + uint16_t length; + uint16_t iter_index; + uint8_t branket_deepth; + struct LexToken token1; + struct LexToken token2; + Arg* last_token; + Args* iter_buffs; + Args* buffs_p; +}; + +char* Parser_multiLineToAsm(Args* outBuffs, char* multiLine); +char* instructUnit_fromAsmLine(Args* outBuffs, char* pikaAsm); +char* Parser_byteCodeToAsm(Args* outBuffs, char* pikaByteCode); +ByteCodeFrame* byteCodeFrame_appendFromAsm(ByteCodeFrame* bf, char* pikaAsm); +int bytecodeFrame_fromMultiLine(ByteCodeFrame* bytecode_frame, + char* python_lines); +void Parser_compilePyToBytecodeArray(char* lines); +#define ParserState_forEach(parseState) \ + ParserState_beforeIter(&parseState); \ + for (int i = 0; i < parseState.length; i++) + +#define ParserState_forEachTokenExistPs(parseState, tokens) \ + /* init parserStage */ \ + ParserState_init(&parseState); \ + ParserState_parse(&parseState, tokens); \ + ParserState_forEach(parseState) + +#define ParserState_forEachToken(parseState, tokens) \ + struct ParserState ps; \ + ParserState_forEachTokenExistPs(parseState, tokens) + +#endif diff --git a/port/linux/package/pikascript/pikascript-core/PikaPlatform.c b/port/linux/package/pikascript/pikascript-core/PikaPlatform.c new file mode 100644 index 000000000..a922632d8 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/PikaPlatform.c @@ -0,0 +1,131 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "PikaPlatform.h" +#include +#include + +PIKA_WEAK void __platform_disable_irq_handle(void) { + /* disable irq to support thread */ +} +PIKA_WEAK void __platform_enable_irq_handle(void) { + /* disable irq to support thread */ +} +PIKA_WEAK void* __platform_malloc(size_t size) { + return malloc(size); +} +PIKA_WEAK void __platform_error_handle(){ + return; +} +PIKA_WEAK void __platform_free(void* ptr) { + free(ptr); +} +PIKA_WEAK uint8_t __is_locked_pikaMemory(void) { + return 0; +} +#ifndef __platform_printf +PIKA_WEAK void __platform_printf(char* fmt, ...) { + va_list args; + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); +} +#endif + +PIKA_WEAK int __platform_vsprintf(char* buff, char* fmt, va_list args) { + return vsprintf(buff, fmt, args); +} + +PIKA_WEAK int __platform_vsnprintf(char* buff, + size_t size, + const char* fmt, + va_list args) { + return vsnprintf(buff, size, fmt, args); +} + +PIKA_WEAK int __platform_sprintf(char* buff, char* fmt, ...) { + va_list args; + va_start(args, fmt); + int res = vsnprintf(buff, PIKA_SPRINTF_BUFF_SIZE, fmt, args); + va_end(args); + return res; +} + +PIKA_WEAK void __platform_wait(void) { + while (1) { + }; +} +PIKA_WEAK void* __platform_memset(void* mem, int ch, size_t size) { + return memset(mem, ch, size); +} + +PIKA_WEAK void* __platform_memcpy(void* dir, const void* src, size_t size) { + return memcpy(dir, src, size); +} + +PIKA_WEAK char __platform_getchar(void) { +#ifdef __linux + return getchar(); +#else + __platform_printf("[error]: __platform_function need implementation!\r\n"); + while (1) { + } +#endif +} + +PIKA_WEAK FILE* __platform_fopen(const char* filename, const char* modes) { +#ifdef __linux + return fopen(filename, modes); +#else + __platform_printf("[error]: __platform_function need implementation!\r\n"); + while (1) { + } +#endif +} + +PIKA_WEAK int __platform_fclose(FILE* stream) { +#ifdef __linux + return fclose(stream); +#else + __platform_printf("[error]: __platform_function need implementation!\r\n"); + while (1) { + } +#endif +} + +PIKA_WEAK size_t __platform_fwrite(const void* ptr, + size_t size, + size_t n, + FILE* stream) { +#ifdef __linux + return fwrite(ptr, size, n, stream); +#else + __platform_printf("[error]: __platform_function need implementation!\r\n"); + while (1) { + } +#endif +} diff --git a/port/linux/package/pikascript/pikascript-core/PikaPlatform.h b/port/linux/package/pikascript/pikascript-core/PikaPlatform.h new file mode 100644 index 000000000..65cca22ba --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/PikaPlatform.h @@ -0,0 +1,104 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* micro pika configuration */ +#include "./pika_config_valid.h" + +#ifndef __PIKA_PALTFORM__H +#define __PIKA_PALTFORM__H +#include +#include +#include +#include +#include + +/* Compiler */ +#if defined(__CC_ARM) || defined(__CLANG_ARM) /* ARM Compiler */ +#define PIKA_WEAK __attribute__((weak)) +#elif defined(__IAR_SYSTEMS_ICC__) /* for IAR Compiler */ +#define PIKA_WEAK __weak +#elif defined(__GNUC__) /* GNU GCC Compiler */ +#define PIKA_WEAK __attribute__((weak)) +#endif +/* default PIKA_WEAK */ +#ifndef PIKA_WEAK +#define PIKA_WEAK +#endif + +/* OS */ +#ifdef __RTTHREAD__ +#include +#define __platform_printf(...) rt_kprintf(__VA_ARGS__) +#endif + +/* + [Note]: + Create a pika_config.c to override the following weak functions to config + PikaScript. [Example]: + 1. + https://gitee.com/Lyon1998/pikascript/blob/master/package/STM32G030Booter/pika_config.c + 2. + https://gitee.com/Lyon1998/pikascript/blob/master/package/pikaRTBooter/pika_config.c +*/ + +/* interrupt config */ +void __platform_enable_irq_handle(void); +void __platform_disable_irq_handle(void); + +/* printf family config */ +#ifndef __platform_printf +void __platform_printf(char* fmt, ...); +#endif +int __platform_sprintf(char* buff, char* fmt, ...); +int __platform_vsprintf(char* buff, char* fmt, va_list args); +int __platform_vsnprintf(char* buff, + size_t size, + const char* fmt, + va_list args); + +/* libc config */ +void* __platform_malloc(size_t size); +void __platform_free(void* ptr); +void* __platform_memset(void* mem, int ch, size_t size); +void* __platform_memcpy(void* dir, const void* src, size_t size); + +/* pika memory pool config */ +void __platform_wait(void); +uint8_t __is_locked_pikaMemory(void); + +/* support shell */ +char __platform_getchar(void); + +/* file API */ +FILE* __platform_fopen(const char* filename, const char* modes); +int __platform_fclose(FILE* stream); +size_t __platform_fwrite(const void* ptr, size_t size, size_t n, FILE* stream); + +/* error */ +void __platform_error_handle(void); + +#endif diff --git a/port/linux/package/pikascript/pikascript-core/PikaVM.c b/port/linux/package/pikascript/pikascript-core/PikaVM.c new file mode 100644 index 000000000..e5c258fc8 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/PikaVM.c @@ -0,0 +1,1455 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define __PIKA_OBJ_CLASS_IMPLEMENT +#include "PikaVM.h" +#include "BaseObj.h" +#include "PikaObj.h" +#include "PikaParser.h" +#include "PikaPlatform.h" +#include "dataStrs.h" + +/* head declear start */ +static uint8_t VMState_getInputArgNum(VMState* vs); + +/* head declear end */ + +static InstructUnit* VMState_getInstructNow(VMState* vs) { + return instructArray_getByOffset(&(vs->bytecode_frame->instruct_array), + vs->pc); +} + +static void VMState_setErrorCode(VMState* vs, uint8_t error_code) { + vs->error_code = error_code; +} + +static InstructUnit* VMState_getInstructWithOffset(VMState* vs, + int32_t offset) { + return instructArray_getByOffset(&(vs->bytecode_frame->instruct_array), + vs->pc + offset); +} + +static int VMState_getBlockDeepthNow(VMState* vs) { + /* support run byteCode */ + InstructUnit* ins_unit = VMState_getInstructNow(vs); + return instructUnit_getBlockDeepth(ins_unit); +} + +static char* VMState_getConstWithInstructUnit(VMState* vs, + InstructUnit* ins_unit) { + return constPool_getByOffset(&(vs->bytecode_frame->const_pool), + instructUnit_getConstPoolIndex(ins_unit)); +} + +static int32_t VMState_getAddrOffsetOfJUM(VMState* vs) { + int offset = 0; + InstructUnit* ins_unit_now = VMState_getInstructNow(vs); + while (1) { + offset += instructUnit_getSize(ins_unit_now); + ins_unit_now = VMState_getInstructWithOffset(vs, offset); + uint16_t invoke_deepth = instructUnit_getInvokeDeepth(ins_unit_now); + enum Instruct ins = instructUnit_getInstruct(ins_unit_now); + char* data = VMState_getConstWithInstructUnit(vs, ins_unit_now); + if ((0 == invoke_deepth) && (JMP == ins) && strEqu(data, "-1")) { + return offset; + } + } +} + +static size_t VMState_getInstructArraySize(VMState* vs) { + return instructArray_getSize(&(vs->bytecode_frame->instruct_array)); +} + +static int32_t VMState_getAddrOffsetFromJmp(VMState* vs) { + int offset = 0; + /* run byte Code */ + InstructUnit* this_ins_unit = VMState_getInstructNow(vs); + int thisBlockDeepth = instructUnit_getBlockDeepth(this_ins_unit); + int8_t blockNum = 0; + + if (vs->jmp > 0) { + offset = 0; + while (1) { + offset += instructUnit_getSize(); + /* reach the end */ + if (vs->pc + offset >= (int)VMState_getInstructArraySize(vs)) { + break; + } + this_ins_unit = VMState_getInstructWithOffset(vs, offset); + if (instructUnit_getIsNewLine(this_ins_unit)) { + uint8_t blockDeepth = + instructUnit_getBlockDeepth(this_ins_unit); + if (blockDeepth <= thisBlockDeepth) { + blockNum++; + } + } + if (blockNum >= vs->jmp) { + break; + } + } + } + if (vs->jmp < 0) { + while (1) { + offset -= instructUnit_getSize(); + this_ins_unit = VMState_getInstructWithOffset(vs, offset); + if (instructUnit_getIsNewLine(this_ins_unit)) { + uint8_t blockDeepth = + instructUnit_getBlockDeepth(this_ins_unit); + if (blockDeepth == thisBlockDeepth) { + blockNum--; + } + } + if (blockNum <= vs->jmp) { + break; + } + } + } + return offset; +} + +static int32_t VMState_getAddrOffsetOfBreak(VMState* vs) { + int32_t offset = VMState_getAddrOffsetOfJUM(vs); + /* byteCode */ + offset += instructUnit_getSize(); + return offset; +} + +static int32_t VMState_getAddrOffsetOfContinue(VMState* vs) { + int32_t offset = VMState_getAddrOffsetOfJUM(vs); + /* byteCode */ + return offset; +} + +typedef Arg* (*VM_instruct_handler)(PikaObj* self, VMState* vs, char* data); + +static Arg* VM_instruction_handler_NON(PikaObj* self, VMState* vs, char* data) { + return NULL; +} + +static Arg* VM_instruction_handler_NEW(PikaObj* self, VMState* vs, char* data) { + Arg* origin_arg = obj_getArg(vs->locals, data); + Arg* new_arg = arg_copy(origin_arg); + origin_arg = arg_setType(origin_arg, ARG_TYPE_REF_OBJECT); + arg_setType(new_arg, ARG_TYPE_FREE_OBJECT); + return new_arg; +} + +static Arg* VM_instruction_handler_REF(PikaObj* self, VMState* vs, char* data) { + if (strEqu(data, (char*)"True")) { + return arg_setInt(NULL, "", 1); + } + if (strEqu(data, (char*)"False")) { + return arg_setInt(NULL, "", 0); + } + /* find in local list first */ + Arg* arg = arg_copy(obj_getArg(vs->locals, data)); + if (NULL == arg) { + /* find in global list second */ + arg = arg_copy(obj_getArg(vs->globals, data)); + } + ArgType arg_type = arg_getType(arg); + if (ARG_TYPE_OBJECT == arg_type) { + arg = arg_setType(arg, ARG_TYPE_REF_OBJECT); + } + if (NULL == arg) { + VMState_setErrorCode(vs, 1); + __platform_printf("NameError: name '%s' is not defined\r\n", data); + } + return arg; +} + +static Arg* VMState_runMethodArg(VMState* vs, + PikaObj* method_host_obj, + PikaObj* sub_locals, + Arg* method_arg) { + Arg* return_arg = NULL; + /* get method Ptr */ + Method method_ptr = methodArg_getPtr(method_arg); + /* get method type list */ + ArgType method_type = arg_getType(method_arg); + ByteCodeFrame* method_bytecodeFrame = + methodArg_getBytecodeFrame(method_arg); + obj_setErrorCode(method_host_obj, 0); + + /* run method */ + if (method_type == ARG_TYPE_NATIVE_METHOD) { + /* native method */ + method_ptr(method_host_obj, sub_locals->list); + /* get method return */ + return_arg = arg_copy(args_getArg(sub_locals->list, (char*)"return")); + } else if (method_type == ARG_TYPE_NATIVE_CONSTRUCTOR_METHOD) { + /* native method */ + method_ptr(method_host_obj, sub_locals->list); + /* get method return */ + return_arg = arg_copy(args_getArg(sub_locals->list, (char*)"return")); + } else { + /* static method and object method */ + /* byteCode */ + uintptr_t insturctArray_start = (uintptr_t)instructArray_getByOffset( + &(method_bytecodeFrame->instruct_array), 0); + uint16_t pc = (uintptr_t)method_ptr - insturctArray_start; + sub_locals = pikaVM_runByteCodeWithState( + method_host_obj, sub_locals, vs->globals, method_bytecodeFrame, pc); + + /* get method return */ + return_arg = arg_copy(args_getArg(sub_locals->list, (char*)"return")); + } + return return_arg; +} + +static void VMState_loadArgsFromMethodArg(VMState* vs, + PikaObj* method_host_obj, + Args* args, + Arg* method_arg, + char* method_name) { + Args buffs = {0}; + /* get method type list */ + char* type_list = methodArg_getTypeList(method_arg, &buffs); + ArgType method_type = arg_getType(method_arg); + uint8_t arg_num_dec = 0; + if (strEqu("", type_list)) { + arg_num_dec = 0; + } else { + arg_num_dec = strCountSign(type_list, ',') + 1; + } + if (method_type == ARG_TYPE_OBJECT_METHOD) { + /* delete the 'self' */ + arg_num_dec--; + } + uint8_t arg_num_input = VMState_getInputArgNum(vs); + + /* check arg num */ + if (method_type == ARG_TYPE_NATIVE_CONSTRUCTOR_METHOD || + method_type == ARG_TYPE_CONSTRUCTOR_METHOD) { + /* not check decleard arg num for constrctor */ + } else { + /* check arg num decleard and input */ + if (arg_num_dec != arg_num_input) { + VMState_setErrorCode(vs, 3); + __platform_printf( + "TypeError: %s() takes %d positional argument but %d were " + "given\r\n", + method_name, arg_num_dec, arg_num_input); + goto exit; + } + } + + /* load pars */ + for (int i = 0; i < arg_num_dec; i++) { + char* argDef = strPopLastToken(type_list, ','); + strPopLastToken(argDef, ':'); + char* argName = argDef; + Arg* call_arg = stack_popArg(&(vs->stack)); + call_arg = arg_setName(call_arg, argName); + args_setArg(args, call_arg); + } + + /* load 'self' as the first arg when call object method */ + if (method_type == ARG_TYPE_OBJECT_METHOD) { + Arg* call_arg = + arg_setPtr(NULL, "self", ARG_TYPE_REF_OBJECT, method_host_obj); + args_setArg(args, call_arg); + } +exit: + strsDeinit(&buffs); +} + +#if PIKA_BUILTIN_LIST_ENABLE +void PikaStdData_List_append(PikaObj* self, Arg* arg); +void PikaStdData_List___init__(PikaObj* self); +PikaObj* New_PikaStdData_List(Args* args); +static Arg* VM_instruction_handler_LST(PikaObj* self, VMState* vs, char* data) { + uint8_t arg_num = VMState_getInputArgNum(vs); + Arg* list_arg = obj_newObjInPackage(New_PikaStdData_List); + PikaObj* list = arg_getPtr(list_arg); + PikaStdData_List___init__(list); + Stack stack = {0}; + stack_init(&stack); + /* load to local stack to change sort */ + for (int i = 0; i < arg_num; i++) { + Arg* arg = stack_popArg(&(vs->stack)); + stack_pushArg(&stack, arg); + } + for (int i = 0; i < arg_num; i++) { + Arg* arg = stack_popArg(&stack); + PikaStdData_List_append(list, arg); + arg_deinit(arg); + } + stack_deinit(&stack); + return list_arg; +} +#endif + +static Arg* VM_instruction_handler_RUN(PikaObj* self, VMState* vs, char* data) { + Args buffs = {0}; + Arg* return_arg = NULL; + VMParameters* sub_locals = NULL; + char* methodPath = data; + PikaObj* method_host_obj; + Arg* method_arg = NULL; + char* sys_out; + /* return arg directly */ + if (strEqu(data, "")) { + return_arg = stack_popArg(&(vs->stack)); + goto exit; + } + + /* get method host obj */ + method_host_obj = obj_getObj(self, methodPath, 1); + if (NULL == method_host_obj) { + method_host_obj = obj_getObj(vs->locals, methodPath, 1); + } + if (NULL == method_host_obj) { + /* error, not found object */ + VMState_setErrorCode(vs, 1); + __platform_printf("Error: method '%s' no found.\r\n", data); + goto exit; + } + /* get method in local */ + method_arg = obj_getMethodArg(method_host_obj, methodPath); + if (NULL == method_arg) { + method_arg = obj_getMethodArg(vs->globals, methodPath); + } + /* assert method*/ + if (NULL == method_arg) { + /* error, method no found */ + VMState_setErrorCode(vs, 2); + __platform_printf("NameError: name '%s' is not defined\r\n", data); + + goto exit; + } + + sub_locals = New_PikaObj(); + /* load args from vmState to sub_local->list */ + VMState_loadArgsFromMethodArg(vs, method_host_obj, sub_locals->list, + method_arg, data); + + /* load args faild */ + if (vs->error_code != 0) { + goto exit; + } + + /* run method arg */ + return_arg = + VMState_runMethodArg(vs, method_host_obj, sub_locals, method_arg); + + /* __init__() */ + if (arg_getType(return_arg) == ARG_TYPE_FREE_OBJECT) { + /* init object */ + PikaObj* new_obj = arg_getPtr(return_arg); + Arg* method_arg = obj_getMethodArg(new_obj, "__init__"); + PikaObj* sub_locals = New_PikaObj(); + Arg* return_arg = NULL; + if (NULL == method_arg) { + uint16_t arg_input_num = VMState_getInputArgNum(vs); + if (arg_input_num != 0) { + VMState_setErrorCode(vs, 3); + __platform_printf("TypeError: %s() takes no arguments\r\n", + data); + /* clear input args */ + for (int i = 0; i < arg_input_num; i++) { + arg_deinit(stack_popArg(&(vs->stack))); + } + } + goto init_exit; + } + VMState_loadArgsFromMethodArg(vs, new_obj, sub_locals->list, method_arg, + "__init__"); + /* load args faild */ + if (vs->error_code != 0) { + goto init_exit; + } + return_arg = VMState_runMethodArg(vs, new_obj, sub_locals, method_arg); + init_exit: + if (NULL != return_arg) { + arg_deinit(return_arg); + } + obj_deinit(sub_locals); + arg_deinit(method_arg); + } + + /* transfer sysOut */ + sys_out = obj_getSysOut(method_host_obj); + if (NULL != sys_out) { + args_setSysOut(vs->locals->list, sys_out); + } + /* transfer errCode */ + if (0 != obj_getErrorCode(method_host_obj)) { + /* method error */ + VMState_setErrorCode(vs, 6); + } + + goto exit; +exit: + if (NULL != method_arg) { + arg_deinit(method_arg); + } + if (NULL != sub_locals) { + obj_deinit(sub_locals); + } + strsDeinit(&buffs); + return return_arg; +} + +static char* __get_transferd_str(Args* buffs, char* str, size_t* iout_p) { + char* transfered_str = args_getBuff(buffs, strGetSize(str)); + size_t i_out = 0; + for (size_t i = 0; i < strGetSize(str); i++) { + /* eg. replace '\x33' to '3' */ + if ((str[i] == '\\') && (str[i + 1] == 'x')) { + char hex_str[] = "0x00"; + hex_str[2] = str[i + 2]; + hex_str[3] = str[i + 3]; + char hex = (char)strtol(hex_str, NULL, 0); + transfered_str[i_out++] = hex; + i += 3; + continue; + } + /* normal char */ + transfered_str[i_out++] = str[i]; + } + *iout_p = i_out; + return transfered_str; +} + +static Arg* VM_instruction_handler_STR(PikaObj* self, VMState* vs, char* data) { + if (strIsContain(data, '\\')) { + Args buffs = {0}; + size_t i_out = 0; + char* transfered_str = __get_transferd_str(&buffs, data, &i_out); + Arg* return_arg = New_arg(NULL); + return_arg = arg_setStr(return_arg, "", transfered_str); + strsDeinit(&buffs); + return return_arg; + } + return arg_setStr(NULL, "", data); +} + +static Arg* VM_instruction_handler_BYT(PikaObj* self, VMState* vs, char* data) { + if (strIsContain(data, '\\')) { + Args buffs = {0}; + size_t i_out = 0; + char* transfered_str = __get_transferd_str(&buffs, data, &i_out); + Arg* return_arg = New_arg(NULL); + return_arg = + arg_setBytes(return_arg, "", (uint8_t*)transfered_str, i_out); + strsDeinit(&buffs); + return return_arg; + } + return arg_setBytes(NULL, "", (uint8_t*)data, strGetSize(data)); +} + +static Arg* VM_instruction_handler_OUT(PikaObj* self, VMState* vs, char* data) { + Arg* outArg = stack_popArg(&(vs->stack)); + ArgType outArg_type = arg_getType(outArg); + PikaObj* hostObj = vs->locals; + /* match global_list */ + if (args_isArgExist(vs->locals->list, "__gl")) { + char* global_list = args_getStr(vs->locals->list, "__gl"); + /* use a arg as buff */ + Arg* global_list_arg = arg_setStr(NULL, "", global_list); + char* global_list_buff = arg_getStr(global_list_arg); + /* for each arg arg in global_list */ + char token_buff[32] = {0}; + for (int i = 0; i < strCountSign(global_list, ',') + 1; i++) { + char* global_arg = strPopToken(token_buff, global_list_buff, ','); + /* matched global arg, hostObj set to global */ + if (strEqu(global_arg, data)) { + hostObj = vs->globals; + } + } + arg_deinit(global_list_arg); + } + /* use RunAs object */ + if (args_isArgExist(vs->locals->list, "__runAs")) { + hostObj = args_getPtr(vs->locals->list, "__runAs"); + } + /* set free object to nomal object */ + if (ARG_TYPE_FREE_OBJECT == outArg_type) { + arg_setType(outArg, ARG_TYPE_OBJECT); + arg_refCntInc(outArg); + } + + /* ouput arg to locals */ + obj_setArg_noCopy(hostObj, data, outArg); + if (ARG_TYPE_MATE_OBJECT == outArg_type) { + /* found a mate_object */ + /* init object */ + PikaObj* new_obj = obj_getObj(hostObj, data, 0); + /* run __init__() when init obj */ + obj_runNativeMethod(new_obj, "__init__", NULL); + } + return NULL; +} + +/* run as */ +static Arg* VM_instruction_handler_RAS(PikaObj* self, VMState* vs, char* data) { + if (strEqu(data, "$origin")) { + /* use origin object to run */ + obj_removeArg(vs->locals, "__runAs"); + return NULL; + } + /* use "data" object to run */ + PikaObj* runAs = obj_getObj(vs->locals, data, 0); + args_setRefObject(vs->locals->list, "__runAs", runAs); + return NULL; +} + +static Arg* VM_instruction_handler_NUM(PikaObj* self, VMState* vs, char* data) { + Arg* numArg = New_arg(NULL); + /* hex */ + if (data[1] == 'x' || data[1] == 'X') { + return arg_setInt(numArg, "", strtol(data, NULL, 0)); + } + /* float */ + if (strIsContain(data, '.')) { + return arg_setFloat(numArg, "", atof(data)); + } + /* int */ + return arg_setInt(numArg, "", fast_atoi(data)); +} + +static Arg* VM_instruction_handler_JMP(PikaObj* self, VMState* vs, char* data) { + vs->jmp = fast_atoi(data); + return NULL; +} + +static Arg* VM_instruction_handler_JEZ(PikaObj* self, VMState* vs, char* data) { + int thisBlockDeepth; + thisBlockDeepth = VMState_getBlockDeepthNow(vs); + Arg* assertArg = stack_popArg(&(vs->stack)); + int assert = arg_getInt(assertArg); + arg_deinit(assertArg); + char __else[] = "__else0"; + __else[6] = '0' + thisBlockDeepth; + args_setInt(self->list, __else, !assert); + if (0 == assert) { + /* set __else flag */ + vs->jmp = fast_atoi(data); + } + return NULL; +} + +static uint8_t VMState_getInputArgNum(VMState* vs) { + InstructUnit* ins_unit_now = VMState_getInstructNow(vs); + uint8_t invode_deepth_this = instructUnit_getInvokeDeepth(ins_unit_now); + int32_t pc_this = vs->pc; + uint8_t num = 0; + while (1) { + ins_unit_now--; + pc_this -= instructUnit_getSize(ins_unit_now); + uint8_t invode_deepth = instructUnit_getInvokeDeepth(ins_unit_now); + if (invode_deepth == invode_deepth_this + 1) { + num++; + } + if (instructUnit_getIsNewLine(ins_unit_now)) { + break; + } + if (invode_deepth <= invode_deepth_this) { + break; + } + if (pc_this <= 0) { + break; + } + } + return num; +} + +static Arg* VM_instruction_handler_OPT(PikaObj* self, VMState* vs, char* data) { + Arg* outArg = NULL; + uint8_t input_arg_num = VMState_getInputArgNum(vs); + Arg* arg2 = NULL; + Arg* arg1 = NULL; + if (input_arg_num == 2) { + /* tow input */ + arg2 = stack_popArg(&(vs->stack)); + arg1 = stack_popArg(&(vs->stack)); + } else if (input_arg_num == 1) { + /* only one input */ + arg2 = stack_popArg(&(vs->stack)); + arg1 = arg_setNull(NULL); + } + ArgType type_arg1 = arg_getType(arg1); + ArgType type_arg2 = arg_getType(arg2); + int num1_i = 0; + int num2_i = 0; + float num1_f = 0.0; + float num2_f = 0.0; + /* get int and float num */ + if (type_arg1 == ARG_TYPE_INT) { + num1_i = arg_getInt(arg1); + num1_f = (float)num1_i; + } else if (type_arg1 == ARG_TYPE_FLOAT) { + num1_f = arg_getFloat(arg1); + num1_i = (int)num1_f; + } + if (type_arg2 == ARG_TYPE_INT) { + num2_i = arg_getInt(arg2); + num2_f = (float)num2_i; + } else if (type_arg2 == ARG_TYPE_FLOAT) { + num2_f = arg_getFloat(arg2); + num2_i = (int)num2_f; + } + if (strEqu("+", data)) { + if ((type_arg1 == ARG_TYPE_STRING) && (type_arg2 == ARG_TYPE_STRING)) { + char* num1_s = NULL; + char* num2_s = NULL; + Args str_opt_buffs = {0}; + num1_s = arg_getStr(arg1); + num2_s = arg_getStr(arg2); + char* opt_str_out = strsAppend(&str_opt_buffs, num1_s, num2_s); + outArg = arg_setStr(outArg, "", opt_str_out); + strsDeinit(&str_opt_buffs); + goto OPT_exit; + } + /* match float */ + if ((type_arg1 == ARG_TYPE_FLOAT) || type_arg2 == ARG_TYPE_FLOAT) { + outArg = arg_setFloat(outArg, "", num1_f + num2_f); + goto OPT_exit; + } + /* int is default */ + outArg = arg_setInt(outArg, "", num1_i + num2_i); + goto OPT_exit; + } + if (strEqu("-", data)) { + if (type_arg2 == ARG_TYPE_NONE) { + if (type_arg1 == ARG_TYPE_INT) { + outArg = arg_setInt(outArg, "", -num1_i); + goto OPT_exit; + } + if (type_arg1 == ARG_TYPE_FLOAT) { + outArg = arg_setFloat(outArg, "", -num1_f); + goto OPT_exit; + } + } + if ((type_arg1 == ARG_TYPE_FLOAT) || type_arg2 == ARG_TYPE_FLOAT) { + outArg = arg_setFloat(outArg, "", num1_f - num2_f); + goto OPT_exit; + } + outArg = arg_setInt(outArg, "", num1_i - num2_i); + goto OPT_exit; + } + if (strEqu("*", data)) { + if ((type_arg1 == ARG_TYPE_FLOAT) || type_arg2 == ARG_TYPE_FLOAT) { + outArg = arg_setFloat(outArg, "", num1_f * num2_f); + goto OPT_exit; + } + outArg = arg_setInt(outArg, "", num1_i * num2_i); + goto OPT_exit; + } + if (strEqu("/", data)) { + if (0 == num2_f) { + VMState_setErrorCode(vs, 1); + args_setSysOut(vs->locals->list, + "ZeroDivisionError: division by zero"); + outArg = NULL; + goto OPT_exit; + } + outArg = arg_setFloat(outArg, "", num1_f / num2_f); + goto OPT_exit; + } + if (strEqu("<", data)) { + outArg = arg_setInt(outArg, "", num1_f < num2_f); + goto OPT_exit; + } + if (strEqu(">", data)) { + outArg = arg_setInt(outArg, "", num1_f > num2_f); + goto OPT_exit; + } + if (strEqu("%", data)) { + outArg = arg_setInt(outArg, "", num1_i % num2_i); + goto OPT_exit; + } + if (strEqu("**", data)) { + float res = 1; + for (int i = 0; i < num2_i; i++) { + res = res * num1_f; + } + outArg = arg_setFloat(outArg, "", res); + goto OPT_exit; + } + if (strEqu("//", data)) { + outArg = arg_setInt(outArg, "", num1_i / num2_i); + goto OPT_exit; + } + if (strEqu("==", data)) { + /* string compire */ + if ((type_arg1 == ARG_TYPE_STRING) && (type_arg2 == ARG_TYPE_STRING)) { + outArg = arg_setInt(outArg, "", + strEqu(arg_getStr(arg1), arg_getStr(arg2))); + goto OPT_exit; + } + /* default: int and float */ + outArg = + arg_setInt(outArg, "", + (num1_f - num2_f) * (num1_f - num2_f) < (float)0.000001); + goto OPT_exit; + } + if (strEqu("!=", data)) { + outArg = arg_setInt( + outArg, "", + !((num1_f - num2_f) * (num1_f - num2_f) < (float)0.000001)); + goto OPT_exit; + } + if (strEqu(">=", data)) { + outArg = arg_setInt( + outArg, "", + (num1_f > num2_f) || + ((num1_f - num2_f) * (num1_f - num2_f) < (float)0.000001)); + goto OPT_exit; + } + if (strEqu("<=", data)) { + outArg = arg_setInt( + outArg, "", + (num1_f < num2_f) || + ((num1_f - num2_f) * (num1_f - num2_f) < (float)0.000001)); + goto OPT_exit; + } + if (strEqu("&", data)) { + outArg = arg_setInt(outArg, "", num1_i & num2_i); + goto OPT_exit; + } + if (strEqu("|", data)) { + outArg = arg_setInt(outArg, "", num1_i | num2_i); + goto OPT_exit; + } + if (strEqu("~", data)) { + outArg = arg_setInt(outArg, "", ~num1_i); + goto OPT_exit; + } + if (strEqu(">>", data)) { + outArg = arg_setInt(outArg, "", num1_i >> num2_i); + goto OPT_exit; + } + if (strEqu("<<", data)) { + outArg = arg_setInt(outArg, "", num1_i << num2_i); + goto OPT_exit; + } + if (strEqu(" and ", data)) { + outArg = arg_setInt(outArg, "", num1_i && num2_i); + goto OPT_exit; + } + if (strEqu(" or ", data)) { + outArg = arg_setInt(outArg, "", num1_i || num2_i); + goto OPT_exit; + } + if (strEqu(" not ", data)) { + outArg = arg_setInt(outArg, "", !num1_i); + goto OPT_exit; + } +OPT_exit: + arg_deinit(arg1); + arg_deinit(arg2); + if (NULL != outArg) { + return outArg; + } + return NULL; +} + +static Arg* __VM_instruction_handler_DEF(PikaObj* self, + VMState* vs, + char* data, + uint8_t is_class) { + int thisBlockDeepth = VMState_getBlockDeepthNow(vs); + + PikaObj* hostObj = vs->locals; + uint8_t is_in_class = 0; + /* use RunAs object */ + if (args_isArgExist(vs->locals->list, "__runAs")) { + hostObj = args_getPtr(vs->locals->list, "__runAs"); + is_in_class = 1; + } + int offset = 0; + /* byteCode */ + while (1) { + InstructUnit* ins_unit_now = VMState_getInstructWithOffset(vs, offset); + if (!instructUnit_getIsNewLine(ins_unit_now)) { + offset += instructUnit_getSize(); + continue; + } + if (instructUnit_getBlockDeepth(ins_unit_now) == thisBlockDeepth + 1) { + if (is_in_class) { + class_defineObjectMethod(hostObj, data, (Method)ins_unit_now, + vs->bytecode_frame); + } else { + if (is_class) { + class_defineRunTimeConstructor(hostObj, data, + (Method)ins_unit_now, + vs->bytecode_frame); + } else { + class_defineStaticMethod(hostObj, data, + (Method)ins_unit_now, + vs->bytecode_frame); + } + } + break; + } + offset += instructUnit_getSize(); + } + + return NULL; +} + +static Arg* VM_instruction_handler_DEF(PikaObj* self, VMState* vs, char* data) { + return __VM_instruction_handler_DEF(self, vs, data, 0); +} + +static Arg* VM_instruction_handler_CLS(PikaObj* self, VMState* vs, char* data) { + return __VM_instruction_handler_DEF(self, vs, data, 1); +} + +static Arg* VM_instruction_handler_RET(PikaObj* self, VMState* vs, char* data) { + /* exit jmp signal */ + vs->jmp = -999; + Arg* returnArg = stack_popArg(&(vs->stack)); + method_returnArg(vs->locals->list, returnArg); + return NULL; +} + +static Arg* VM_instruction_handler_NEL(PikaObj* self, VMState* vs, char* data) { + int thisBlockDeepth = VMState_getBlockDeepthNow(vs); + char __else[] = "__else0"; + __else[6] = '0' + thisBlockDeepth; + if (0 == args_getInt(self->list, __else)) { + /* set __else flag */ + vs->jmp = fast_atoi(data); + } + return NULL; +} + +static Arg* VM_instruction_handler_DEL(PikaObj* self, VMState* vs, char* data) { + obj_removeArg(vs->locals, data); + return NULL; +} + +static Arg* VM_instruction_handler_EST(PikaObj* self, VMState* vs, char* data) { + Arg* arg = obj_getArg(vs->locals, data); + if (arg == NULL) { + return arg_setInt(NULL, "", 0); + } + if (ARG_TYPE_NULL == arg_getType(arg)) { + return arg_setInt(NULL, "", 0); + } + return arg_setInt(NULL, "", 1); +} + +static Arg* VM_instruction_handler_BRK(PikaObj* self, VMState* vs, char* data) { + /* break jmp signal */ + vs->jmp = -998; + return NULL; +} + +static Arg* VM_instruction_handler_CTN(PikaObj* self, VMState* vs, char* data) { + /* continue jmp signal */ + vs->jmp = -997; + return NULL; +} + +static Arg* VM_instruction_handler_GLB(PikaObj* self, VMState* vs, char* data) { + Arg* global_list_buff = NULL; + char* global_list = args_getStr(vs->locals->list, "__gl"); + /* create new global_list */ + if (NULL == global_list) { + args_setStr(vs->locals->list, "__gl", data); + goto exit; + } + /* append to exist global_list */ + global_list_buff = arg_setStr(NULL, "", global_list); + global_list_buff = arg_strAppend(global_list_buff, ","); + global_list_buff = arg_strAppend(global_list_buff, data); + args_setStr(vs->locals->list, "__gl", arg_getStr(global_list_buff)); + goto exit; +exit: + if (NULL != global_list_buff) { + arg_deinit(global_list_buff); + } + return NULL; +} + +const VM_instruct_handler VM_instruct_handler_table[__INSTRCUTION_CNT] = { +#define __INS_TABLE +#include "__instruction_table.cfg" +}; + +enum Instruct pikaVM_getInstructFromAsm(char* line) { +#define __INS_COMPIRE +#include "__instruction_table.cfg" + return NON; +} + +static int pikaVM_runInstructUnit(PikaObj* self, + VMState* vs, + InstructUnit* ins_unit) { + enum Instruct instruct = instructUnit_getInstruct(ins_unit); + Arg* resArg; + // char invode_deepth1_str[2] = {0}; + int32_t pc_next = vs->pc + instructUnit_getSize(); + char* data = VMState_getConstWithInstructUnit(vs, ins_unit); + /* run instruct */ + resArg = VM_instruct_handler_table[instruct](self, vs, data); + if (NULL != resArg) { + stack_pushArg(&(vs->stack), resArg); + } + goto nextLine; +nextLine: + /* exit */ + if (-999 == vs->jmp) { + pc_next = -99999; + goto exit; + } + /* break */ + if (-998 == vs->jmp) { + pc_next = vs->pc + VMState_getAddrOffsetOfBreak(vs); + goto exit; + } + /* continue */ + if (-997 == vs->jmp) { + pc_next = vs->pc + VMState_getAddrOffsetOfContinue(vs); + goto exit; + } + /* static jmp */ + if (vs->jmp != 0) { + pc_next = vs->pc + VMState_getAddrOffsetFromJmp(vs); + goto exit; + } + /* not jmp */ + pc_next = vs->pc + instructUnit_getSize(); + goto exit; +exit: + vs->jmp = 0; + /* reach the end */ + if (pc_next >= (int)VMState_getInstructArraySize(vs)) { + return -99999; + } + return pc_next; +} + +VMParameters* pikaVM_runAsm(PikaObj* self, char* pikaAsm) { + ByteCodeFrame bytecode_frame; + byteCodeFrame_init(&bytecode_frame); + byteCodeFrame_appendFromAsm(&bytecode_frame, pikaAsm); + VMParameters* res = pikaVM_runByteCodeFrame(self, &bytecode_frame); + byteCodeFrame_deinit(&bytecode_frame); + return res; +} + +VMParameters* pikaVM_runPyLines_or_byteCode(PikaObj* self, + char* py_lines, + uint8_t* bytecode) { + uint8_t is_run_py; + if (NULL != py_lines) { + is_run_py = 1; + } else if (NULL != bytecode) { + is_run_py = 0; + } else { + return NULL; + } + Args buffs = {0}; + VMParameters* globals = NULL; + ByteCodeFrame bytecode_frame_stack = {0}; + ByteCodeFrame* bytecode_frame_p = NULL; + uint8_t is_use_heap_bytecode = 0; + + /* + * the first obj_run, cache bytecode to heap, to support 'def' and 'class' + */ + if (!args_isArgExist(self->list, "__first_bytecode")) { + is_use_heap_bytecode = 1; + /* load bytecode to heap */ + args_setHeapStruct(self->list, "__first_bytecode", bytecode_frame_stack, + byteCodeFrame_deinit); + /* get bytecode_ptr from heap */ + bytecode_frame_p = args_getHeapStruct(self->list, "__first_bytecode"); + } else { + /* not the first obj_run */ + /* save 'def' and 'class' to heap */ + if ((strIsStartWith(py_lines, "def ")) || + (strIsStartWith(py_lines, "class "))) { + char* declear_name = strsGetFirstToken(&buffs, py_lines, ':'); + /* load bytecode to heap */ + args_setHeapStruct(self->list, declear_name, bytecode_frame_stack, + byteCodeFrame_deinit); + /* get bytecode_ptr from heap */ + bytecode_frame_p = args_getHeapStruct(self->list, declear_name); + } else { + /* get bytecode_ptr from stack */ + bytecode_frame_p = &bytecode_frame_stack; + } + } + + /* load or generate byte code frame */ + if (is_run_py) { + /* generate byte code */ + byteCodeFrame_init(bytecode_frame_p); + if (1 == bytecodeFrame_fromMultiLine(bytecode_frame_p, py_lines)) { + __platform_printf("[error]: Syntax error.\r\n"); + globals = NULL; + goto exit; + } + } else { + /* load bytecode */ + byteCodeFrame_loadBytes(bytecode_frame_p, bytecode); + } + + /* run byteCode */ + globals = pikaVM_runByteCodeFrame(self, bytecode_frame_p); + goto exit; +exit: + if (!is_use_heap_bytecode) { + byteCodeFrame_deinit(&bytecode_frame_stack); + } + strsDeinit(&buffs); + return globals; +} + +VMParameters* pikaVM_run(PikaObj* self, char* py_lines) { + return pikaVM_runPyLines_or_byteCode(self, py_lines, NULL); +} + +VMParameters* pikaVM_runByteCode(PikaObj* self, uint8_t* bytecode) { + return pikaVM_runPyLines_or_byteCode(self, NULL, bytecode); +} + +static void* constPool_getStart(ConstPool* self) { + return self->content_start; +} + +void constPool_update(ConstPool* self) { + self->content_start = (void*)arg_getContent(self->arg_buff); +} + +void constPool_init(ConstPool* self) { + self->arg_buff = arg_setStr(NULL, "", ""); + constPool_update(self); + self->content_offset_now = 0; + self->size = strGetSize(constPool_getStart(self)) + 1; + self->output_redirect_fun = NULL; + self->output_f = NULL; +} + +void constPool_deinit(ConstPool* self) { + if (NULL != self->arg_buff) { + arg_deinit(self->arg_buff); + } +} + +void constPool_append(ConstPool* self, char* content) { + uint16_t size = strGetSize(content) + 1; + if (NULL == self->output_redirect_fun) { + self->arg_buff = arg_append(self->arg_buff, content, size); + } else { + self->output_redirect_fun(self, content); + }; + constPool_update(self); + self->size += size; +} + +char* constPool_getNow(ConstPool* self) { + if (self->content_offset_now >= self->size) { + /* is the end */ + return NULL; + } + return (char*)((uintptr_t)constPool_getStart(self) + + (uintptr_t)(self->content_offset_now)); +} + +uint16_t constPool_getLastOffset(ConstPool* self) { + return self->size; +} + +uint16_t constPool_getOffsetByData(ConstPool* self, char* data) { + uint16_t ptr_befor = self->content_offset_now; + /* set ptr_now to begin */ + self->content_offset_now = 0; + uint16_t offset_out = 65535; + while (1) { + if (NULL == constPool_getNext(self)) { + goto exit; + } + if (strEqu(data, constPool_getNow(self))) { + offset_out = self->content_offset_now; + goto exit; + } + } +exit: + /* retore ptr_now */ + self->content_offset_now = ptr_befor; + return offset_out; +} + +char* constPool_getNext(ConstPool* self) { + self->content_offset_now += strGetSize(constPool_getNow(self)) + 1; + return constPool_getNow(self); +} + +char* constPool_getByIndex(ConstPool* self, uint16_t index) { + uint16_t ptr_befor = self->content_offset_now; + /* set ptr_now to begin */ + self->content_offset_now = 0; + for (uint16_t i = 0; i < index; i++) { + constPool_getNext(self); + } + char* res = constPool_getNow(self); + /* retore ptr_now */ + self->content_offset_now = ptr_befor; + return res; +} + +void constPool_print(ConstPool* self) { + uint16_t ptr_befor = self->content_offset_now; + /* set ptr_now to begin */ + self->content_offset_now = 0; + while (1) { + if (NULL == constPool_getNext(self)) { + goto exit; + } + uint16_t offset = self->content_offset_now; + __platform_printf("%d: %s\r\n", offset, constPool_getNow(self)); + } +exit: + /* retore ptr_now */ + self->content_offset_now = ptr_befor; + return; +} + +void byteCodeFrame_init(ByteCodeFrame* self) { + /* init to support append, + if only load static bytecode, + can not init */ + constPool_init(&(self->const_pool)); + instructArray_init(&(self->instruct_array)); +} + +void byteCodeFrame_loadBytes(ByteCodeFrame* self, uint8_t* bytes) { + uint16_t* ins_size_p = (uint16_t*)bytes; + void* ins_start_p = (uint16_t*)(bytes + 2); + uint16_t* const_size_p = + (uint16_t*)((uintptr_t)ins_start_p + (uintptr_t)(*ins_size_p)); + self->instruct_array.size = *ins_size_p; + self->instruct_array.content_start = ins_start_p; + self->const_pool.size = *const_size_p; + self->const_pool.content_start = (char*)((uintptr_t)const_size_p + 2); +} + +void byteCodeFrame_deinit(ByteCodeFrame* self) { + constPool_deinit(&(self->const_pool)); + instructArray_deinit(&(self->instruct_array)); +} + +void instructArray_init(InstructArray* self) { + self->arg_buff = arg_setNull(NULL); + instructArray_update(self); + self->size = 0; + self->content_offset_now = 0; + self->output_redirect_fun = NULL; + self->output_f = NULL; +} + +void instructArray_deinit(InstructArray* self) { + if (NULL != self->arg_buff) { + arg_deinit(self->arg_buff); + } +} + +void instructArray_append(InstructArray* self, InstructUnit* ins_unit) { + if (NULL == self->output_redirect_fun) { + self->arg_buff = + arg_append(self->arg_buff, ins_unit, instructUnit_getSize()); + } else { + self->output_redirect_fun(self, ins_unit); + }; + instructArray_update(self); + self->size += instructUnit_getSize(); +} + +void instructUnit_init(InstructUnit* ins_unit) { + ins_unit->deepth = 0; + ins_unit->const_pool_index = 0; + ins_unit->isNewLine_instruct = 0; +} + +static void* instructArray_getStart(InstructArray* self) { + return self->content_start; +} + +void instructArray_update(InstructArray* self) { + self->content_start = (void*)arg_getContent(self->arg_buff); +} + +static InstructUnit* instructArray_getNow(InstructArray* self) { + if (self->content_offset_now >= self->size) { + /* is the end */ + return NULL; + } + return (InstructUnit*)((uintptr_t)instructArray_getStart(self) + + (uintptr_t)(self->content_offset_now)); +} + +static InstructUnit* instructArray_getNext(InstructArray* self) { + self->content_offset_now += instructUnit_getSize(); + return instructArray_getNow(self); +} + +static char* instructUnit_getInstructStr(InstructUnit* self) { +#define __INS_GET_INS_STR +#include "__instruction_table.cfg" + return "NON"; +} + +void instructUnit_print(InstructUnit* self) { + if (instructUnit_getIsNewLine(self)) { + __platform_printf("B%d\r\n", instructUnit_getBlockDeepth(self)); + } + __platform_printf("%d %s #%d\r\n", instructUnit_getInvokeDeepth(self), + instructUnit_getInstructStr(self), + self->const_pool_index); +} + +static void instructUnit_printWithConst(InstructUnit* self, + ConstPool* const_pool) { + // if (instructUnit_getIsNewLine(self)) { + // __platform_printf("B%d\r\n", instructUnit_getBlockDeepth(self)); + // } + __platform_printf("%s %s \t\t(#%d)\r\n", instructUnit_getInstructStr(self), + constPool_getByOffset(const_pool, self->const_pool_index), + self->const_pool_index); +} + +void instructArray_printWithConst(InstructArray* self, ConstPool* const_pool) { + uint16_t offset_befor = self->content_offset_now; + self->content_offset_now = 0; + while (1) { + InstructUnit* ins_unit = instructArray_getNow(self); + if (NULL == ins_unit) { + goto exit; + } + instructUnit_printWithConst(ins_unit, const_pool); + instructArray_getNext(self); + } +exit: + self->content_offset_now = offset_befor; + return; +} + +void instructArray_print(InstructArray* self) { + uint16_t offset_befor = self->content_offset_now; + self->content_offset_now = 0; + while (1) { + InstructUnit* ins_unit = instructArray_getNow(self); + if (NULL == ins_unit) { + goto exit; + } + instructUnit_print(ins_unit); + instructArray_getNext(self); + } +exit: + self->content_offset_now = offset_befor; + return; +} + +void instructArray_printAsArray(InstructArray* self) { + uint16_t offset_befor = self->content_offset_now; + self->content_offset_now = 0; + uint8_t line_num = 12; + uint16_t g_i = 0; + uint8_t* ins_size_p = (uint8_t*)&self->size; + __platform_printf("0x%02x, ", *(ins_size_p)); + __platform_printf("0x%02x, ", *(ins_size_p + (uintptr_t)1)); + __platform_printf("/* instruct array size */\n"); + while (1) { + InstructUnit* ins_unit = instructArray_getNow(self); + if (NULL == ins_unit) { + goto exit; + } + for (int i = 0; i < (int)instructUnit_getSize(ins_unit); i++) { + g_i++; + __platform_printf("0x%02x, ", *((uint8_t*)ins_unit + (uintptr_t)i)); + if (g_i % line_num == 0) { + __platform_printf("\n"); + } + } + instructArray_getNext(self); + } +exit: + __platform_printf("/* instruct array */\n"); + self->content_offset_now = offset_befor; + return; +} + +size_t byteCodeFrame_getSize(ByteCodeFrame* bf) { + return bf->const_pool.size + bf->instruct_array.size; +} + +void byteCodeFrame_print(ByteCodeFrame* self) { + constPool_print(&(self->const_pool)); + instructArray_printWithConst(&(self->instruct_array), &(self->const_pool)); + __platform_printf("---------------\r\n"); + __platform_printf("byte code size: %d\r\n", + self->const_pool.size + self->instruct_array.size); +} + +void VMState_solveUnusedStack(VMState* vs) { + uint8_t top = stack_getTop(&(vs->stack)); + for (int i = 0; i < top; i++) { + Arg* arg = stack_popArg(&(vs->stack)); + ArgType type = arg_getType(arg); + if (type == ARG_TYPE_VOID) { + arg_deinit(arg); + continue; + } + if (vs->line_error_code != 0) { + arg_deinit(arg); + continue; + } + if (type == ARG_TYPE_INT) { + __platform_printf("%d\r\n", (int)arg_getInt(arg)); + } else if (type == ARG_TYPE_FLOAT) { + __platform_printf("%f\r\n", arg_getFloat(arg)); + } else if (type == ARG_TYPE_STRING) { + __platform_printf("%s\r\n", arg_getStr(arg)); + } else if (type == ARG_TYPE_BYTES) { + arg_printBytes(arg); + } + arg_deinit(arg); + } +} + +VMParameters* pikaVM_runByteCodeWithState(PikaObj* self, + VMParameters* locals, + VMParameters* globals, + ByteCodeFrame* bytecode_frame, + uint16_t pc) { + int size = bytecode_frame->instruct_array.size; + VMState vs = { + .bytecode_frame = bytecode_frame, + .locals = locals, + .globals = globals, + .jmp = 0, + .pc = pc, + .error_code = 0, + .line_error_code = 0, + }; + stack_init(&(vs.stack)); + while (vs.pc < size) { + if (vs.pc == -99999) { + break; + } + InstructUnit* this_ins_unit = VMState_getInstructNow(&vs); + if (instructUnit_getIsNewLine(this_ins_unit)) { + VMState_solveUnusedStack(&vs); + stack_reset(&(vs.stack)); + vs.error_code = 0; + vs.line_error_code = 0; + } + vs.pc = pikaVM_runInstructUnit(self, &vs, this_ins_unit); + if (0 != vs.error_code) { + vs.line_error_code = vs.error_code; + InstructUnit* head_ins_unit = this_ins_unit; + /* get first ins of a line */ + while (1) { + if (instructUnit_getIsNewLine(head_ins_unit)) { + break; + } + head_ins_unit--; + } + /* print inses of a line */ + while (1) { + if (head_ins_unit != this_ins_unit) { + __platform_printf(" "); + } else { + __platform_printf(" -> "); + } + instructUnit_printWithConst(head_ins_unit, + &(bytecode_frame->const_pool)); + head_ins_unit++; + if (head_ins_unit > this_ins_unit) { + break; + } + } + __platform_error_handle(); + vs.error_code = 0; + } + } + VMState_solveUnusedStack(&vs); + stack_deinit(&(vs.stack)); + return locals; +} + +VMParameters* pikaVM_runByteCodeFrame(PikaObj* self, + ByteCodeFrame* byteCode_frame) { + return pikaVM_runByteCodeWithState(self, self, self, byteCode_frame, 0); +} + +char* constPool_getByOffset(ConstPool* self, uint16_t offset) { + return (char*)((uintptr_t)constPool_getStart(self) + (uintptr_t)offset); +} + +InstructUnit* instructArray_getByOffset(InstructArray* self, int32_t offset) { + return (InstructUnit*)((uintptr_t)instructArray_getStart(self) + + (uintptr_t)offset); +} + +void constPool_printAsArray(ConstPool* self) { + uint8_t* const_size_str = (uint8_t*)&(self->size); + __platform_printf("0x%02x, ", *(const_size_str)); + __platform_printf("0x%02x, ", *(const_size_str + (uintptr_t)1)); + __platform_printf("/* const pool size */\n"); + uint16_t ptr_befor = self->content_offset_now; + uint8_t line_num = 12; + uint16_t g_i = 0; + /* set ptr_now to begin */ + self->content_offset_now = 0; + __platform_printf("0x00, "); + while (1) { + if (NULL == constPool_getNext(self)) { + goto exit; + } + char* data_each = constPool_getNow(self); + /* todo start */ + for (uint32_t i = 0; i < strGetSize(data_each) + 1; i++) { + __platform_printf("0x%02x, ", *(data_each + (uintptr_t)i)); + g_i++; + if (g_i % line_num == 0) { + __platform_printf("\n"); + } + } + /* todo end */ + } +exit: + /* retore ptr_now */ + __platform_printf("/* const pool */\n"); + self->content_offset_now = ptr_befor; + return; +} + +void byteCodeFrame_printAsArray(ByteCodeFrame* self) { + __platform_printf("const uint8_t bytes[] = {\n"); + instructArray_printAsArray(&(self->instruct_array)); + constPool_printAsArray(&(self->const_pool)); + __platform_printf("};\n"); + __platform_printf("pikaVM_runByteCode(self, (uint8_t*)bytes);\n"); +} diff --git a/port/linux/package/pikascript/pikascript-core/PikaVM.h b/port/linux/package/pikascript/pikascript-core/PikaVM.h new file mode 100644 index 000000000..7978a8b28 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/PikaVM.h @@ -0,0 +1,137 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __PIKA_VM__H +#define __PIKA_VM__H +#include "PikaObj.h" +#include "dataQueue.h" +#include "dataStack.h" +#include "dataQueueObj.h" + +enum Instruct { +#define __INS_ENUM +#include "__instruction_table.cfg" + __INSTRCUTION_CNT, +}; + +typedef struct VMState_t { + VMParameters* locals; + VMParameters* globals; + Stack stack; + int32_t jmp; + int32_t pc; + ByteCodeFrame* bytecode_frame; + uint8_t error_code; + uint8_t line_error_code; +} VMState; + +VMParameters* pikaVM_run(PikaObj* self, char* pyLine); +VMParameters* pikaVM_runAsm(PikaObj* self, char* pikaAsm); +VMParameters* pikaVM_runByteCodeFrame(PikaObj* self, + ByteCodeFrame* byteCode_frame); + +#define instructUnit_getBlockDeepth(self) (((self)->deepth) & 0x0F) +#define instructUnit_getInvokeDeepth(self) (((self)->deepth) >> 4) +#define instructUnit_getInstruct(self) \ + ((enum Instruct)((self)->isNewLine_instruct & 0x7F)) +#define instructUnit_getConstPoolIndex(self) ((self)->const_pool_index) +#define instructUnit_getIsNewLine(self) ((self)->isNewLine_instruct >> 7) + +#define instructUnit_setBlockDeepth(self, val) \ + do { \ + ((self)->deepth) |= (0x0F & (val)); \ + } while (0) + +#define instructUnit_setConstPoolIndex(self, val) \ + do { \ + ((self)->const_pool_index = (val)); \ + } while (0) + +#define instructUnit_setInvokeDeepth(self, val) \ + do { \ + ((self)->deepth) |= ((0x0F & (val)) << 4); \ + } while (0) + +#define instructUnit_setInstruct(self, val) \ + do { \ + ((self)->isNewLine_instruct) |= (0x7F & (val)); \ + } while (0) + +#define instructUnit_setIsNewLine(self, val) \ + do { \ + ((self)->isNewLine_instruct) |= ((0x01 & (val)) << 7); \ + } while (0) + +InstructUnit* New_instructUnit(uint8_t data_size); +void instructUnit_deinit(InstructUnit* self); + +enum Instruct pikaVM_getInstructFromAsm(char* line); + +void constPool_init(ConstPool* self); +void constPool_deinit(ConstPool* self); +void constPool_append(ConstPool* self, char* content); +char* constPool_getNow(ConstPool* self); +char* constPool_getNext(ConstPool* self); +char* constPool_getByIndex(ConstPool* self, uint16_t index); +char* constPool_getByOffset(ConstPool* self, uint16_t offset); +uint16_t constPool_getLastOffset(ConstPool* self); +void constPool_print(ConstPool* self); + +void byteCodeFrame_init(ByteCodeFrame* bf); +void byteCodeFrame_deinit(ByteCodeFrame* bf); +size_t byteCodeFrame_getSize(ByteCodeFrame* bf); + +void instructArray_init(InstructArray* ins_array); +void instructArray_deinit(InstructArray* ins_array); +void instructArray_append(InstructArray* ins_array, InstructUnit* ins_unit); +void instructUnit_init(InstructUnit* ins_unit); +void instructUnit_print(InstructUnit* self); +void instructArray_print(InstructArray* self); +void byteCodeFrame_print(ByteCodeFrame* self); +InstructUnit* instructArray_getByOffset(InstructArray* self, int32_t offset); + +#define instructUnit_getSize(InstructUnit_p_self) ((size_t)sizeof(InstructUnit)) +#define instructArray_getSize(InsturctArry_p_self) \ + ((size_t)(InsturctArry_p_self)->size) + +VMParameters* pikaVM_runByteCodeWithState(PikaObj* self, + VMParameters* locals, + VMParameters* globals, + ByteCodeFrame* bytecode_frame, + uint16_t pc); + +uint16_t constPool_getOffsetByData(ConstPool* self, char* data); +void instructArray_printWithConst(InstructArray* self, ConstPool* const_pool); +void constPool_update(ConstPool* self); +void instructArray_update(InstructArray* self); +void constPool_printAsArray(ConstPool* self); +void instructArray_printAsArray(InstructArray* self); +void byteCodeFrame_loadBytes(ByteCodeFrame* self, uint8_t* bytes); +void byteCodeFrame_printAsArray(ByteCodeFrame* self); +VMParameters* pikaVM_runByteCode(PikaObj* self, uint8_t* bytecode); + +#endif diff --git a/port/linux/package/pikascript/pikascript-core/README.md b/port/linux/package/pikascript/pikascript-core/README.md new file mode 100644 index 000000000..ea47272db --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/README.md @@ -0,0 +1 @@ +# PikaScript 运行时内核 diff --git a/port/linux/package/pikascript/pikascript-core/TinyObj.c b/port/linux/package/pikascript/pikascript-core/TinyObj.c new file mode 100644 index 000000000..bbcaa57c9 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/TinyObj.c @@ -0,0 +1,41 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "PikaObj.h" + +void _UpdateHandle(PikaObj* self) { + // override the handle function here +} + +void _beforDinit(PikaObj* self) { + /* override in user code */ +} + +PikaObj* New_TinyObj(Args* args) { + PikaObj* self = New_PikaObj(); + return self; +} diff --git a/port/linux/package/pikascript/pikascript-core/TinyObj.h b/port/linux/package/pikascript/pikascript-core/TinyObj.h new file mode 100644 index 000000000..72d388efe --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/TinyObj.h @@ -0,0 +1,32 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __TYNYOBJ__H +#define __TYNYOBJ__H +#include "PikaObj.h" +PikaObj* New_TinyObj(Args* args); +#endif diff --git a/port/linux/package/pikascript/pikascript-core/__instruction_def.h b/port/linux/package/pikascript/pikascript-core/__instruction_def.h new file mode 100644 index 000000000..84c419c1d --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/__instruction_def.h @@ -0,0 +1,54 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 GorgonMeducer ?? embedded_zhuoran@hotmail.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#undef def_ins + +#if defined(__INS_ENUM) +#define def_ins(__INS_NAME) __INS_NAME, +#endif + +#if defined(__INS_TABLE) +#define def_ins(__INS_NAME) [__INS_NAME] = &VM_instruction_handler_##__INS_NAME, +#endif + +#if defined(__INS_COMPIRE) +#define def_ins(__INS_NAME) \ + if (0 == strncmp(line + 2, "" #__INS_NAME "", 3)) { \ + return __INS_NAME; \ + } +#endif + +#if defined(__INS_GET_INS_STR) +#define def_ins(__INS_NAME) \ + if (__INS_NAME == instructUnit_getInstruct(self)){ \ + return ""#__INS_NAME""; \ + } +#endif + +#undef __INS_ENUM +#undef __INS_TABLE +#undef __INS_COMPIRE diff --git a/port/linux/package/pikascript/pikascript-core/__instruction_table.cfg b/port/linux/package/pikascript/pikascript-core/__instruction_table.cfg new file mode 100644 index 000000000..9c656b1cf --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/__instruction_table.cfg @@ -0,0 +1,56 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 GorgonMeducer ?? embedded_zhuoran@hotmail.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "__instruction_def.h" + +//! just append ins to the end, insert ins would brake the pre-compiled +//! bytecode. + +def_ins(NON) +def_ins(REF) +def_ins(RUN) +def_ins(STR) +def_ins(OUT) +def_ins(NUM) +def_ins(JMP) +def_ins(JEZ) +def_ins(OPT) +def_ins(DEF) +def_ins(RET) +def_ins(NEL) +def_ins(DEL) +def_ins(EST) +def_ins(BRK) +def_ins(CTN) +def_ins(GLB) +def_ins(RAS) +def_ins(NEW) +def_ins(CLS) +def_ins(BYT) +#if PIKA_BUILTIN_LIST_ENABLE +def_ins(LST) +#endif diff --git a/port/linux/package/pikascript/pikascript-core/__pika_ooc.h b/port/linux/package/pikascript/pikascript-core/__pika_ooc.h new file mode 100644 index 000000000..d529fe931 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/__pika_ooc.h @@ -0,0 +1,34 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon ?? liang6516@outlook.com + * Copyright (c) 2021 Gorgon Meducer ?? embedded_zhuoran@hotmail.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __PIKA_OOC_H__ +#define __PIKA_OOC_H__ + +// #include "./3rd-party/PLOOC/plooc_class.h" + +#endif diff --git a/port/linux/package/pikascript/pikascript-core/dataArg.c b/port/linux/package/pikascript/pikascript-core/dataArg.c new file mode 100644 index 000000000..0ee2d8ad2 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/dataArg.c @@ -0,0 +1,363 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "dataArg.h" +#include "dataArgs.h" +#include "dataMemory.h" +#include "dataString.h" +#include "stdlib.h" + +uint16_t arg_getTotleSize(Arg* self) { + return content_totleSize(self); +} + +/** + * time33 hash + */ +Hash hash_time33(char* str) { + Hash hash = 5381; + while (*str) { + hash += (hash << 5) + (*str++); + } + return (hash & 0x7FFFFFFF); +} + +static uint8_t* content_init_hash(Hash nameHash, + ArgType type, + uint8_t* content, + uint32_t size, + uint8_t* next) { + __arg* self = (__arg*)pikaMalloc(sizeof(__arg) + size); + + self->next = (__arg*)next; + self->size = size; + self->name_hash = nameHash; + self->type = type; + + if (NULL != content) { + __platform_memcpy(self->content, content, size); + } else { + __platform_memset(self->content, 0, size); + } + + return (uint8_t*)self; +} + +static uint8_t* content_init(char* name, + ArgType type, + uint8_t* content, + uint16_t size, + uint8_t* next) { + Hash nameHash = hash_time33(name); + return content_init_hash(nameHash, type, content, size, next); +} + +uint16_t content_totleSize(uint8_t* self) { + return ((__arg*)self)->size + sizeof(__arg); +} + +void arg_freeContent(Arg* self) { + if (NULL != self) { + content_deinit(self); + } +} + +uint8_t* content_deinit(uint8_t* self) { + uint16_t totleSize = content_totleSize(self); + pikaFree(self, totleSize); + return 0; +} + +uint8_t* content_setContent(uint8_t* self, uint8_t* content, uint16_t size) { + if (NULL == self) { + /* malloc */ + return content_init("", ARG_TYPE_VOID, content, size, NULL); + } + + /* only copy */ + if (content_getSize(self) == size) { + __platform_memcpy(((__arg*)self)->content, content, size); + return self; + } + + /* realloc */ + Hash nameHash = content_getNameHash(self); + ArgType type = content_getType(self); + uint8_t* next = content_getNext(self); + uint8_t* newContent = + content_init_hash(nameHash, type, content, size, next); + content_deinit(self); + return newContent; +} + +uint8_t* content_setNameHash(uint8_t* self, Hash nameHash) { + if (NULL == self) { + return content_init_hash(nameHash, ARG_TYPE_VOID, NULL, 0, NULL); + } + __arg* arg = (__arg*)self; + arg->name_hash = nameHash; + return self; +} + +uint8_t* content_setName(uint8_t* self, char* name) { + return content_setNameHash(self, hash_time33(name)); +} + +uint8_t* content_setType(uint8_t* self, ArgType type) { + if (NULL == self) { + return content_init("", type, NULL, 0, NULL); + } + + __arg* arg = (__arg*)self; + arg->type = type; + + return self; +} + +ArgType content_getType(uint8_t* self) { + __arg* arg = (__arg*)self; + return (ArgType)arg->type; +} + +Arg* arg_setBytes(Arg* self, char* name, uint8_t* src, size_t size) { + self = arg_newContent(self, size + sizeof(size_t)); + self = arg_setName(self, name); + self = arg_setType(self, ARG_TYPE_BYTES); + void* dir = arg_getContent(self); + __platform_memcpy(dir, &size, sizeof(size_t)); + __platform_memcpy((void*)((uintptr_t)dir + sizeof(size_t)), src, size); + return self; +} + +Arg* arg_newContent(Arg* self, uint32_t size) { + uint8_t* newContent = content_init("", ARG_TYPE_VOID, NULL, size, NULL); + arg_freeContent(self); + return newContent; +} + +Arg* arg_setContent(Arg* self, uint8_t* content, uint32_t size) { + return content_setContent(self, content, size); +} + +uint8_t* arg_getBytes(Arg* self) { + return content_getContent(self) + sizeof(size_t); +} + +void arg_printBytes(Arg* self) { + size_t bytes_size = arg_getBytesSize(self); + uint8_t* bytes = arg_getBytes(self); + __platform_printf("b\'"); + for (size_t i = 0; i < bytes_size; i++) { + __platform_printf("\\x%02x", bytes[i]); + } + __platform_printf("\'\r\n"); +} + +size_t arg_getBytesSize(Arg* self) { + size_t mem_size = 0; + void* content = (void*)arg_getContent(self); + if (NULL == content) { + return 0; + } + __platform_memcpy(&mem_size, content, sizeof(size_t)); + return mem_size; +} + +Arg* arg_setStruct(Arg* self, + char* name, + void* struct_ptr, + uint32_t struct_size) { + if (NULL == struct_ptr) { + return NULL; + } + Arg* struct_arg = arg_setContent(NULL, (uint8_t*)struct_ptr, struct_size); + struct_arg = arg_setType(struct_arg, ARG_TYPE_STRUCT); + struct_arg = arg_setName(struct_arg, name); + return struct_arg; +} + +Arg* arg_setHeapStruct(Arg* self, + char* name, + void* struct_ptr, + uint32_t struct_size, + void* struct_deinit_fun) { + if (NULL == struct_ptr) { + return NULL; + } + Arg* struct_arg = + arg_setContent(NULL, (uint8_t*)&struct_deinit_fun, sizeof(void*)); + struct_arg = arg_append(struct_arg, (uint8_t*)struct_ptr, struct_size); + struct_arg = arg_setType(struct_arg, ARG_TYPE_HEAP_STRUCT); + struct_arg = arg_setName(struct_arg, name); + return struct_arg; +} + +void* arg_getHeapStructDeinitFun(Arg* self) { + void* deinit_fun = NULL; + __platform_memcpy(&deinit_fun, arg_getContent(self), sizeof(void*)); + return deinit_fun; +} + +Arg* arg_setName(Arg* self, char* name) { + return content_setName(self, name); +} + +Arg* arg_setNameHash(Arg* self, Hash nameHash) { + return content_setNameHash(self, nameHash); +} + +Arg* arg_setType(Arg* self, ArgType type) { + return content_setType(self, type); +} + +Arg* arg_setInt(Arg* self, char* name, int64_t val) { + return content_init(name, ARG_TYPE_INT, (uint8_t*)&val, sizeof(val), NULL); +} + +Arg* arg_setNull(Arg* self) { + return content_init("", ARG_TYPE_NULL, NULL, 0, NULL); +} + +Arg* arg_setFloat(Arg* self, char* name, float val) { + return content_init(name, ARG_TYPE_FLOAT, (uint8_t*)&val, sizeof(val), + NULL); +} + +float arg_getFloat(Arg* self) { + if (NULL == arg_getContent(self)) { + return -999.999; + } + + return *(float*)(((__arg*)self)->content); +} + +Arg* arg_setPtr(Arg* self, char* name, ArgType type, void* pointer) { + return content_init(name, type, (uint8_t*)&pointer, sizeof(uintptr_t), + NULL); +} + +Arg* arg_setStr(Arg* self, char* name, char* string) { + return content_init(name, ARG_TYPE_STRING, (uint8_t*)string, + strGetSize(string) + 1, NULL); +} + +int64_t arg_getInt(Arg* self) { + if (NULL == arg_getContent(self)) { + return -999999; + } + return *(int64_t*)(((__arg*)self)->content); +} + +void* arg_getPtr(Arg* self) { + if (NULL == arg_getContent(self)) { + return NULL; + } + return *(void**)(((__arg*)self)->content); +} +char* arg_getStr(Arg* self) { + return (char*)arg_getContent(self); +} + +Hash arg_getNameHash(Arg* self) { + if (NULL == self) { + return 999999; + } + return content_getNameHash(self); +} + +ArgType arg_getType(Arg* self) { + if (NULL == self) { + return ARG_TYPE_NULL; + } + return content_getType(self); +} + +uint16_t arg_getContentSize(Arg* self) { + return content_getSize(self); +} + +Arg* New_arg(void* voidPointer) { + return NULL; +} + +Arg* arg_copy(Arg* argToBeCopy) { + if (NULL == argToBeCopy) { + return NULL; + } + Arg* argCopied = New_arg(NULL); + argCopied = arg_setContent(argCopied, arg_getContent(argToBeCopy), + arg_getContentSize(argToBeCopy)); + argCopied = arg_setNameHash(argCopied, arg_getNameHash(argToBeCopy)); + argCopied = arg_setType(argCopied, arg_getType(argToBeCopy)); + return argCopied; +} + +Arg* arg_append(Arg* arg_in, void* new_content, size_t new_size) { + uint8_t* old_content = arg_getContent(arg_in); + size_t old_size = arg_getContentSize(arg_in); + /* create arg_out */ + Arg* arg_out = arg_setContent(NULL, NULL, old_size + new_size); + arg_setType(arg_out, arg_getType(arg_in)); + arg_setNameHash(arg_out, arg_getNameHash(arg_in)); + /* copy old content */ + __platform_memcpy(arg_getContent(arg_out), old_content, old_size); + /* copy new content */ + __platform_memcpy(arg_getContent(arg_out) + old_size, new_content, + new_size); + arg_deinit(arg_in); + return arg_out; +} + +void* arg_getHeapStruct(Arg* self) { + return arg_getContent(self) + sizeof(void*); +} + +void arg_deinitHeap(Arg* self) { + if (arg_getType(self) == ARG_TYPE_HEAP_STRUCT) { + /* deinit heap strcut */ + StructDeinitFun struct_deinit_fun = + (StructDeinitFun)arg_getHeapStructDeinitFun(self); + struct_deinit_fun(arg_getHeapStruct(self)); + } +} + +void arg_deinit(Arg* self) { + arg_deinitHeap(self); + arg_freeContent(self); +} + +void arg_refCntInc(Arg* self) { + ((__arg*)self)->ref_cnt++; +} + +void arg_refCntDec(Arg* self) { + ((__arg*)self)->ref_cnt--; +} + +uint8_t arg_getRefCnt(Arg* self) { + return ((__arg*)self)->ref_cnt; +} diff --git a/port/linux/package/pikascript/pikascript-core/dataArg.h b/port/linux/package/pikascript/pikascript-core/dataArg.h new file mode 100644 index 000000000..eeaae89b4 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/dataArg.h @@ -0,0 +1,146 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _arg__H +#define _arg__H +#include "dataLink.h" +#include "dataMemory.h" + +typedef uint32_t Hash; +typedef enum { + ARG_TYPE_UNDEF = 0, + ARG_TYPE_NONE, + ARG_TYPE_VOID, + ARG_TYPE_BYTES, + ARG_TYPE_NULL, + ARG_TYPE_INT, + ARG_TYPE_FLOAT, + ARG_TYPE_STRING, + ARG_TYPE_OBJECT, + ARG_TYPE_MATE_OBJECT, + ARG_TYPE_FREE_OBJECT, + ARG_TYPE_POINTER, + ARG_TYPE_REF_OBJECT, + ARG_TYPE_NATIVE_METHOD, + ARG_TYPE_NATIVE_CONSTRUCTOR_METHOD, + ARG_TYPE_CONSTRUCTOR_METHOD, + ARG_TYPE_OBJECT_METHOD, + ARG_TYPE_STATIC_METHOD, + ARG_TYPE_STRUCT, + ARG_TYPE_HEAP_STRUCT, +} ArgType; + +typedef void (*StructDeinitFun)(void* struct_); + +typedef struct __arg __arg; +struct __arg { + __arg* next; + uint16_t size; + uint8_t type; + uint8_t ref_cnt; + Hash name_hash; + uint8_t content[]; +}; + +typedef uint8_t Arg; + +// uint32_t content_getNameHash(uint8_t* content); +#define content_getNameHash(__addr) (((__arg*)(__addr))->name_hash) + +ArgType content_getType(uint8_t* self); + +#define content_getNext(__addr) ((uint8_t*)(((__arg*)(__addr))->next)) + +#define content_getSize(__addr) ((uint16_t)(((__arg*)(__addr))->size)) + +#define content_getContent(__addr) (((__arg*)(__addr))->content) + +uint16_t content_totleSize(uint8_t* self); + +uint8_t* content_deinit(uint8_t* self); + +uint8_t* content_setName(uint8_t* self, char* name); +uint8_t* content_setType(uint8_t* self, ArgType type); +uint8_t* content_setContent(uint8_t* self, uint8_t* content, uint16_t size); +// void content_setNext(uint8_t* self, uint8_t* next); + +#define content_setNext(__addr, __next) \ + do { \ + (((__arg*)(__addr))->next) = (__arg*)(__next); \ + } while (0) + +uint16_t arg_getTotleSize(Arg* self); +void arg_freeContent(Arg* self); + +Arg* arg_setName(Arg* self, char* name); +Arg* arg_setContent(Arg* self, uint8_t* content, uint32_t size); +Arg* arg_newContent(Arg* self, uint32_t size); +Arg* arg_setType(Arg* self, ArgType type); +Hash arg_getNameHash(Arg* self); +ArgType arg_getType(Arg* self); +uint16_t arg_getContentSize(Arg* self); +Hash hash_time33(char* str); + +Arg* arg_setInt(Arg* self, char* name, int64_t val); +Arg* arg_setFloat(Arg* self, char* name, float val); +Arg* arg_setPtr(Arg* self, char* name, ArgType type, void* pointer); +Arg* arg_setStr(Arg* self, char* name, char* string); +Arg* arg_setNull(Arg* self); + +int64_t arg_getInt(Arg* self); +float arg_getFloat(Arg* self); +void* arg_getPtr(Arg* self); +char* arg_getStr(Arg* self); +uint8_t* arg_getBytes(Arg* self); +size_t arg_getBytesSize(Arg* self); +Arg* arg_copy(Arg* argToBeCopy); + +#define arg_getContent(self) ((uint8_t*)content_getContent((self))) + +Arg* arg_init(Arg* self, void* voidPointer); +void arg_deinit(Arg* self); + +Arg* New_arg(void* voidPointer); +Arg* arg_append(Arg* arg_in, void* new_content, size_t new_size); +Arg* arg_setStruct(Arg* self, + char* name, + void* struct_ptr, + uint32_t struct_size); +Arg* arg_setHeapStruct(Arg* self, + char* name, + void* struct_ptr, + uint32_t struct_size, + void* struct_deinit_fun); +void* arg_getHeapStruct(Arg* self); +void arg_deinitHeap(Arg* self); +Arg* arg_setBytes(Arg* self, char* name, uint8_t* src, size_t size); +void arg_printBytes(Arg* self); +void arg_refCntInc(Arg* self); +void arg_refCntDec(Arg* self); +uint8_t arg_getRefCnt(Arg* self); + +#endif diff --git a/port/linux/package/pikascript/pikascript-core/dataArgs.c b/port/linux/package/pikascript/pikascript-core/dataArgs.c new file mode 100644 index 000000000..c23da2f9b --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/dataArgs.c @@ -0,0 +1,519 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "dataArgs.h" +#include "PikaObj.h" +#include "PikaPlatform.h" +#include "dataLink.h" +#include "dataMemory.h" +#include "dataString.h" +#include "dataStrs.h" + +void args_deinit(Args* self) { + link_deinit(self); +} + +void args_deinit_stack(Args* self) { + link_deinit_stack(self); +} + +int32_t args_setFloat(Args* self, char* name, float argFloat) { + Arg* argNew = New_arg(NULL); + argNew = arg_setFloat(argNew, name, argFloat); + args_setArg(self, argNew); + return 0; +} + +void* args_getPtr(Args* self, char* name) { + void* pointer = NULL; + Arg* arg = args_getArg(self, name); + if (NULL == arg) { + return NULL; + } + + pointer = arg_getPtr(arg); + return pointer; +} + +int32_t args_setPtr(Args* self, char* name, void* argPointer) { + int32_t errCode = 0; + Arg* argNew = New_arg(NULL); + argNew = arg_setPtr(argNew, name, ARG_TYPE_POINTER, argPointer); + args_setArg(self, argNew); + return errCode; +} + +int32_t args_setRefObject(Args* self, char* name, void* argPointer) { + int32_t errCode = 0; + Arg* argNew = New_arg(NULL); + argNew = arg_setPtr(argNew, name, ARG_TYPE_REF_OBJECT, argPointer); + args_setArg(self, argNew); + return errCode; +} + +int32_t args_setStr(Args* self, char* name, char* strIn) { + int32_t errCode = 0; + Arg* argNew = New_arg(NULL); + argNew = arg_setStr(argNew, name, strIn); + args_setArg(self, argNew); + return errCode; +} + +int args_pushArg(Args* self, Arg* arg) { + link_addNode(self, arg); + return 0; +} + +void args_setBytes(Args* self, char* name, uint8_t* src, size_t size) { + Arg* argNew = arg_setBytes(NULL, name, src, size); + args_setArg(self, argNew); +} + +char* args_getBuff(Args* self, int32_t size) { + Arg* argNew = New_arg(NULL); + argNew = arg_newContent(argNew, size + 1); + args_pushArg(self, argNew); + return (char*)arg_getContent(argNew); +} + +char* args_getStr(Args* self, char* name) { + if (NULL == self) { + return NULL; + } + Arg* arg = args_getArg(self, name); + if (NULL == arg) { + return NULL; + } + if (NULL == arg_getContent(arg)) { + return NULL; + } + return (char*)arg_getContent(arg); +} + +uint8_t* args_getBytes(Args* self, char* name) { + if (NULL == self) { + return NULL; + } + Arg* arg = args_getArg(self, name); + if (NULL == arg) { + return NULL; + } + if (NULL == arg_getContent(arg)) { + return NULL; + } + return arg_getBytes(arg); +} + +size_t args_getBytesSize(Args* self, char* name) { + if (NULL == self) { + return 0; + } + Arg* arg = args_getArg(self, name); + if (NULL == arg) { + return 0; + } + if (NULL == arg_getContent(arg)) { + return 0; + } + return arg_getBytesSize(arg); +} + +int32_t args_setInt(Args* self, char* name, int64_t int64In) { + Arg* argNew = New_arg(NULL); + argNew = arg_setInt(argNew, name, int64In); + args_setArg(self, argNew); + return 0; +} + +int64_t args_getInt(Args* self, char* name) { + Arg* arg = args_getArg(self, name); + if (NULL == arg) { + return -999999999; + } + ArgType arg_type = arg_getType(arg); + if (arg_type == ARG_TYPE_INT) { + return arg_getInt(arg); + } else if (arg_type == ARG_TYPE_FLOAT) { + return (int)arg_getFloat(arg); + } + return -999999999; +} + +int32_t args_getSize(Args* self) { + return link_getSize(self); +} + +ArgType args_getType(Args* self, char* name) { + Arg* arg = NULL; + arg = args_getArg(self, name); + if (NULL == arg) { + return ARG_TYPE_NULL; + } + return arg_getType(arg); +} + +float args_getFloat(Args* self, char* name) { + Arg* arg = args_getArg(self, name); + if (NULL == arg) { + return -999999999.0; + } + ArgType arg_type = arg_getType(arg); + if (arg_type == ARG_TYPE_FLOAT) { + return arg_getFloat(arg); + } else if (arg_type == ARG_TYPE_INT) { + return (float)arg_getInt(arg); + } + return -999999999.0; +} + +int32_t args_copyArg(Args* self, Arg* argToBeCopy) { + if (NULL == argToBeCopy) { + return 1; + } + Arg* argCopied = arg_copy(argToBeCopy); + args_setArg(self, argCopied); + + return 0; +} + +int32_t args_setStructWithSize(Args* self, + char* name, + void* struct_ptr, + uint32_t struct_size) { + Arg* struct_arg = arg_setStruct(NULL, name, struct_ptr, struct_size); + if (NULL == struct_arg) { + /* faild */ + return 1; + } + args_setArg(self, struct_arg); + return 0; +} + +void* args_getStruct(Args* self, char* name) { + Arg* struct_arg = args_getArg(self, name); + return arg_getContent(struct_arg); +} + +void* args_getHeapStruct(Args* self, char* name) { + Arg* struct_arg = args_getArg(self, name); + return arg_getHeapStruct(struct_arg); +} + +int32_t args_setHeapStructWithSize(Args* self, + char* name, + void* struct_ptr, + uint32_t struct_size, + void* struct_deinit_fun) { + Arg* struct_arg = arg_setHeapStruct(NULL, name, struct_ptr, struct_size, + struct_deinit_fun); + if (NULL == struct_arg) { + /* faild */ + return 1; + } + args_setArg(self, struct_arg); + return 0; +} + +int32_t args_copyArgByName(Args* self, char* name, Args* directArgs) { + Arg* argToBeCopy = args_getArg(self, name); + args_copyArg(directArgs, argToBeCopy); + return 0; +} + +int32_t args_isArgExist_hash(Args* self, Hash nameHash) { + if (NULL != args_getArg_hash(self, nameHash)) { + return 1; + } + return 0; +} + +int32_t args_isArgExist(Args* self, char* name) { + if (NULL != args_getArg(self, name)) { + return 1; + } + return 0; +} + +int32_t __updateArg(Args* self, Arg* argNew) { + LinkNode* nodeToUpdate = NULL; + LinkNode* nodeNow = self->firstNode; + LinkNode* priorNode = NULL; + Hash nameHash = arg_getNameHash(argNew); + while (1) { + if (content_getNameHash(nodeNow) == nameHash) { + nodeToUpdate = nodeNow; + break; + } + if (content_getNext(nodeNow) == NULL) { + // error, node no found + goto exit; + } + priorNode = nodeNow; + nodeNow = content_getNext(nodeNow); + } + + arg_deinitHeap(nodeToUpdate); + + nodeToUpdate = arg_setContent(nodeToUpdate, arg_getContent(argNew), + arg_getContentSize(argNew)); + + nodeToUpdate = arg_setType(nodeToUpdate, arg_getType(argNew)); + // update privior link, because arg_getContent would free origin pointer + if (NULL == priorNode) { + self->firstNode = nodeToUpdate; + goto exit; + } + + content_setNext(priorNode, nodeToUpdate); + goto exit; +exit: + arg_freeContent(argNew); + return 0; +} + +int32_t args_setArg(Args* self, Arg* arg) { + Hash nameHash = arg_getNameHash(arg); + if (!args_isArgExist_hash(self, nameHash)) { + args_pushArg(self, arg); + return 0; + } + __updateArg(self, arg); + return 0; +} + +#ifndef __PIKA_CFG_HASH_LIST_CACHE_SIZE +#define __PIKA_CFG_HASH_LIST_CACHE_SIZE 4 +#endif + +LinkNode* args_getNode_hash(Args* self, Hash nameHash) { + LinkNode** ppnode = (LinkNode**)&(self->firstNode); + int_fast8_t n = 0; + + while (NULL != (*ppnode)) { + Arg* arg = (*ppnode); + Hash thisNameHash = arg_getNameHash(arg); + if (thisNameHash == nameHash) { + __arg* tmp = (__arg*)(*ppnode); + if (n > __PIKA_CFG_HASH_LIST_CACHE_SIZE) { + /* the first __PIKA_CFG_HASH_LIST_CACHE_SIZE items in the list + * is considered as a cache. + * Don't make __PIKA_CFG_HASH_LIST_CACHE_SIZE too big, otherwise + * this optimisation is useless. + */ + + /*! remove current node from the list */ + (*ppnode) = (LinkNode*)(tmp->next); + + /*! move the node to the cache */ + tmp->next = (__arg*)(self->firstNode); + self->firstNode = (LinkNode*)tmp; + } + return (LinkNode*)tmp; + } + n++; + ppnode = (LinkNode**)&(((__arg*)(*ppnode))->next); + } + + return NULL; +} + +LinkNode* args_getNode(Args* self, char* name) { + return args_getNode_hash(self, hash_time33(name)); +} + +Arg* args_getArg_hash(Args* self, Hash nameHash) { + LinkNode* node = args_getNode_hash(self, nameHash); + if (NULL == node) { + return NULL; + } + return node; +} + +Arg* args_getArg(Args* self, char* name) { + LinkNode* node = args_getNode(self, name); + if (NULL == node) { + return NULL; + } + return node; +} + +Arg* args_getArg_index(Args* self, int index) { + LinkNode* nodeNow = self->firstNode; + if (NULL == nodeNow) { + return NULL; + } + for (int i = 0; i < index; i++) { + nodeNow = content_getNext(nodeNow); + } + return nodeNow; +} + +char* getPrintSring(Args* self, char* name, char* valString) { + Args buffs = {0}; + char* printName = strsFormat(&buffs, 128, "[printBuff]%s", name); + char* printString = strsCopy(&buffs, valString); + args_setStr(self, printName, printString); + char* res = args_getStr(self, printName); + strsDeinit(&buffs); + return res; +} + +char* getPrintStringFromInt(Args* self, char* name, int32_t val) { + Args buffs = {0}; + char* res = NULL; + char* valString = strsFormat(&buffs, 32, "%d", val); + res = getPrintSring(self, name, valString); + strsDeinit(&buffs); + return res; +} + +char* getPrintStringFromFloat(Args* self, char* name, float val) { + Args buffs = {0}; + char* res = NULL; + char* valString = strsFormat(&buffs, 32, "%f", val); + res = getPrintSring(self, name, valString); + strsDeinit(&buffs); + return res; +} + +char* getPrintStringFromPtr(Args* self, char* name, void* val) { + Args buffs = {0}; + char* res = NULL; + uint64_t intVal = (uintptr_t)val; + char* valString = strsFormat(&buffs, 32, "0x%llx", intVal); + res = getPrintSring(self, name, valString); + strsDeinit(&buffs); + return res; +} + +char* args_print(Args* self, char* name) { + char* res = NULL; + ArgType type = args_getType(self, name); + Args buffs = {0}; + if (ARG_TYPE_NONE == type) { + /* can not get arg */ + res = NULL; + goto exit; + } + + if (type == ARG_TYPE_INT) { + int32_t val = args_getInt(self, name); + res = getPrintStringFromInt(self, name, val); + goto exit; + } + + if (type == ARG_TYPE_FLOAT) { + float val = args_getFloat(self, name); + res = getPrintStringFromFloat(self, name, val); + goto exit; + } + + if (type == ARG_TYPE_STRING) { + res = args_getStr(self, name); + goto exit; + } + + if (type == ARG_TYPE_REF_OBJECT) { + void* val = args_getPtr(self, name); + res = getPrintStringFromPtr(self, name, val); + goto exit; + } + + /* can not match type */ + res = NULL; + goto exit; + +exit: + strsDeinit(&buffs); + return res; +} + +int32_t args_setPtrWithType(Args* self, + char* name, + ArgType type, + void* objPtr) { + Arg* argNew = New_arg(NULL); + argNew = arg_setPtr(argNew, name, type, objPtr); + args_setArg(self, argNew); + return 0; +} + +int32_t args_foreach(Args* self, + int32_t (*eachHandle)(Arg* argEach, Args* handleArgs), + Args* handleArgs) { + if (NULL == self->firstNode) { + return 0; + } + LinkNode* nodeNow = self->firstNode; + while (1) { + Arg* argNow = nodeNow; + if (NULL == argNow) { + continue; + } + LinkNode* nextNode = content_getNext(nodeNow); + eachHandle(argNow, handleArgs); + + if (NULL == nextNode) { + break; + } + nodeNow = nextNode; + } + return 0; +} + +int32_t args_removeArg(Args* self, Arg* argNow) { + if (NULL == argNow) { + /* can not found arg */ + return 1; + } + link_removeNode(self, argNow); + return 0; +} + +int32_t args_removeArg_notDeinitArg(Args* self, Arg* argNow) { + if (NULL == argNow) { + /* can not found arg */ + return 1; + } + link_removeNode_notDeinitNode(self, argNow); + return 0; +} + +int args_moveArg(Args* self, Args* dict, Arg* argNow) { + if (NULL == argNow) { + /* can not found arg */ + return 1; + } + link_removeNode_notDeinitNode(self, argNow); + args_pushArg(dict, argNow); + return 0; +} + +Args* New_args(Args* args) { + Args* self = New_link(NULL); + return self; +} diff --git a/port/linux/package/pikascript/pikascript-core/dataArgs.h b/port/linux/package/pikascript/pikascript-core/dataArgs.h new file mode 100644 index 000000000..c49a32573 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/dataArgs.h @@ -0,0 +1,124 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _dataArgs__H +#define _dataArgs__H +#include "dataArg.h" +#include "dataLink.h" +#include "dataMemory.h" +#include "dataString.h" + +typedef Link Args; + +/* operation */ +void args_deinit(Args* self); +void args_deinit_stack(Args* self); +void args_init(Args* self, Args* args); +int32_t args_getSize(Args* self); +LinkNode* args_getNode(Args* self, char* name); + +Arg* args_getArgByIndex(Args* self, int32_t index); +Arg* args_getArg(Args* self, char* name); +int32_t args_removeArg(Args* self, Arg* argNow); +int args_moveArg(Args* self, Args* dict, Arg* arg); +Arg* args_getArg_hash(Args* self, Hash nameHash); + +int32_t args_setArg(Args* self, Arg* arg); + +int32_t args_copyArgByName(Args* self, char* name, Args* directList); +int32_t args_copyArg(Args* self, Arg* argToBeCopy); + +ArgType args_getType(Args* self, char* name); +int32_t args_isArgExist_hash(Args* self, Hash nameHash); +int32_t args_isArgExist(Args* self, char* name); + +int32_t args_setStr(Args* self, char* name, char* strIn); +int32_t args_setStrWithDefaultName(Args* self, char* strIn); +char* args_getStr(Args* self, char* name); + +int32_t args_setFloatWithDefaultName(Args* self, float argFloat); +int32_t args_setFloat(Args* self, char* name, float argFloat); +float args_getFloat(Args* self, char* name); + +int32_t args_setRefObject(Args* self, char* name, void* argPointer); +int32_t args_setPtr(Args* self, char* name, void* argPointer); +void* args_getPtr(Args* self, char* name); + +int32_t args_setInt(Args* self, char* name, int64_t int64In); +int64_t args_getInt(Args* self, char* name); + +void args_bindInt(Args* self, char* name, int32_t* intPtr); +void args_bindFloat(Args* self, char* name, float* floatPtr); +void args_bindStr(Args* self, char* name, char** stringPtr); +/* arg general opeartion */ +void args_bind(Args* self, char* type, char* name, void* pointer); +char* args_print(Args* self, char* name); + +int32_t args_setStructWithSize(Args* self, + char* name, + void* struct_ptr, + uint32_t struct_size); + +int32_t args_setHeapStructWithSize(Args* self, + char* name, + void* struct_ptr, + uint32_t struct_size, + void* struct_deinit_fun); + +#define args_setStruct(Args_p_self, char_p_name, struct_) \ + args_setStructWithSize((Args_p_self), (char_p_name), &(struct_), \ + sizeof(struct_)) + +#define args_setHeapStruct(Args_p_self, char_p_name, struct_, \ + struct_deinit_fun) \ + args_setHeapStructWithSize((Args_p_self), (char_p_name), &(struct_), \ + sizeof(struct_), (void*)struct_deinit_fun) + +void* args_getStruct(Args* self, char* name); + +int32_t args_set(Args* self, char* name, char* valueStr); +int32_t args_setObjectWithClass(Args* self, + char* objectName, + char* className, + void* objectPtr); +int32_t args_setPtrWithType(Args* self, char* name, ArgType type, void* objPtr); +int32_t args_foreach(Args* self, + int32_t (*eachHandle)(Arg* argEach, Args* handleArgs), + Args* handleArgs); + +char* args_getBuff(Args* self, int32_t size); +uint8_t args_setLiteral(Args* self, char* targetArgName, char* literal); +int args_pushArg(Args* self, Arg* arg); +Arg* args_getArg_index(Args* self, int index); +void* args_getHeapStruct(Args* self, char* name); +int32_t args_removeArg_notDeinitArg(Args* self, Arg* argNow); +uint8_t* args_getBytes(Args* self, char* name); +void args_setBytes(Args* self, char* name, uint8_t* src, size_t size); +size_t args_getBytesSize(Args* self, char* name); + +Args* New_args(Args* args); +#endif diff --git a/port/linux/package/pikascript/pikascript-core/dataLink.c b/port/linux/package/pikascript/pikascript-core/dataLink.c new file mode 100644 index 000000000..fb3b45da2 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/dataLink.c @@ -0,0 +1,129 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "dataLink.h" +#include "dataArg.h" +#include "dataLinkNode.h" +#include "dataMemory.h" + +void __link_deinit_pyload(Link* self) { + LinkNode* nowNode = self->firstNode; + while (NULL != nowNode) { + LinkNode* nodeNext = content_getNext(nowNode); + linkNode_deinit(nowNode); + nowNode = nodeNext; + } + self = NULL; +} + +void link_deinit(Link* self) { + __link_deinit_pyload(self); + pikaFree(self, sizeof(Link)); +} + +void link_deinit_stack(Link* self) { + __link_deinit_pyload(self); +} + +void link_addNode(Link* self, void* content) { + // old first node become new second node + LinkNode* secondNode = self->firstNode; + + self->firstNode = content; + // change the first node to new node + content_setNext(content, secondNode); +} + +static void __link_removeNode(Link* self, + void* content, + uint8_t is_deinit_node) { + LinkNode* nodeToDelete = NULL; + LinkNode* nodeNow = self->firstNode; + LinkNode* priorNode = NULL; + LinkNode* nextNode; + while (1) { + if (nodeNow == content) { + nodeToDelete = nodeNow; + break; + } + if (nodeNow == NULL) { + // error, node no found + goto exit; + } + priorNode = nodeNow; + nodeNow = content_getNext(nodeNow); + } + + nextNode = content_getNext(nodeToDelete); + if (nodeToDelete == self->firstNode) { + self->firstNode = content_getNext(nodeToDelete); + } + + if (NULL == priorNode) { + self->firstNode = nextNode; + goto exit; + } + + content_setNext(priorNode, nextNode); + goto exit; + +// deinit the node +exit: + if (is_deinit_node) { + linkNode_deinit(nodeToDelete); + } + return; +} + +void link_removeNode(Link* self, void* content) { + __link_removeNode(self, content, 1); +} + +void link_removeNode_notDeinitNode(Link* self, void* content) { + __link_removeNode(self, content, 0); +} + +int32_t link_getSize(Link* self) { + LinkNode* NowNode; + int32_t size = 0; + NowNode = self->firstNode; + while (NULL != NowNode) { + size++; + NowNode = content_getNext(NowNode); + } + return size; +} + +void link_init(Link* self, void* args) { + self->firstNode = NULL; +} + +Link* New_link(void* args) { + Link* self = pikaMalloc(sizeof(Link)); + link_init(self, args); + return self; +} diff --git a/port/linux/package/pikascript/pikascript-core/dataLink.h b/port/linux/package/pikascript/pikascript-core/dataLink.h new file mode 100644 index 000000000..ce32b9838 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/dataLink.h @@ -0,0 +1,52 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _link2__H +#define _link2__H +#include "dataLinkNode.h" +#include "dataMemory.h" + +enum LINK_IS_DEINIT_SELF { + LINK_IS_DEINIT_SELF_ENABLE, + LINK_IS_DEINIT_SELF_DISABLE, +}; + +typedef struct Class_link Link; +struct Class_link { + LinkNode* firstNode; +}; + +void link_deinit(Link* self); +void link_deinit_stack(Link* self); +void link_init(Link* self, void* args); +void link_addNode(Link* self, void* content); +void link_removeNode(Link* self, void* content); +void link_removeNode_notDeinitNode(Link* self, void* content); +LinkNode* link_getNode(Link* self, int64_t id); +int32_t link_getSize(Link* self); +Link* New_link(void* args); +#endif diff --git a/port/linux/package/pikascript/pikascript-core/dataLinkNode.c b/port/linux/package/pikascript/pikascript-core/dataLinkNode.c new file mode 100644 index 000000000..9c6f2717f --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/dataLinkNode.c @@ -0,0 +1,42 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "dataLinkNode.h" +#include "dataArg.h" +#include "dataMemory.h" + +void linkNode_deinit(LinkNode* self) { + arg_deinit(self); +} + +void linkNode_init(LinkNode* self, void* args) { + /* attribute */ +} + +LinkNode* New_linkNode(void* args) { + return NULL; +} diff --git a/port/linux/package/pikascript/pikascript-core/dataLinkNode.h b/port/linux/package/pikascript/pikascript-core/dataLinkNode.h new file mode 100644 index 000000000..e3a742e42 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/dataLinkNode.h @@ -0,0 +1,37 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _linkNode__H +#define _linkNode__H +#include "dataMemory.h" +typedef uint8_t LinkNode; + +void linkNode_deinit(LinkNode* self); +void linkNode_init(LinkNode* self, void* args); + +LinkNode* New_linkNode(void* args); +#endif diff --git a/port/linux/package/pikascript/pikascript-core/dataMemory.c b/port/linux/package/pikascript/pikascript-core/dataMemory.c new file mode 100644 index 000000000..384c91ee5 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/dataMemory.c @@ -0,0 +1,296 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "dataMemory.h" +#include "PikaPlatform.h" + +PikaMemInfo pikaMemInfo = {0}; + +void* pikaMalloc(uint32_t size) { + /* pika memory lock */ + if (0 != __is_locked_pikaMemory()) { + __platform_wait(); + } + +//! if you unsure about the __impl_pikaMalloc, uncomment this to force alignment +#if PIKA_ARG_ALIGN_ENABLE + /* force alignment to avoid unaligned access */ + size = (size + 4 - 1) & ~(4 - 1); +#endif + + pikaMemInfo.heapUsed += size; + if (pikaMemInfo.heapUsedMax < pikaMemInfo.heapUsed) { + pikaMemInfo.heapUsedMax = pikaMemInfo.heapUsed; + } + __platform_disable_irq_handle(); + void* mem = __platform_malloc(size); + __platform_enable_irq_handle(); + if (NULL == mem) { + __platform_printf( + "[error]: No heap space! Please reset the device.\r\n"); + while (1) { + } + } + return mem; +} + +void pikaFree(void* mem, uint32_t size) { + if (0 != __is_locked_pikaMemory()) { + __platform_wait(); + } + +//! if you unsure about the __impl_pikaMalloc, uncomment this to force alignment +#if PIKA_ARG_ALIGN_ENABLE + /* force alignment to avoid unaligned access */ + size = (size + 4 - 1) & ~(4 - 1); +#endif + + __platform_disable_irq_handle(); + __platform_free(mem); + __platform_enable_irq_handle(); + pikaMemInfo.heapUsed -= size; +} + +uint16_t pikaMemNow(void) { + return pikaMemInfo.heapUsed; + // return 0; +} + +uint16_t pikaMemMax(void) { + return pikaMemInfo.heapUsedMax; +} + +void pikaMemMaxReset(void) { + pikaMemInfo.heapUsedMax = 0; +} + +uint32_t pool_getBlockIndex_byMemSize(Pool* pool, uint32_t size) { + if (0 == size) { + return 0; + } + return (size - 1) / pool->aline + 1; +} + +uint32_t pool_aline(Pool* pool, uint32_t size) { + return pool_getBlockIndex_byMemSize(pool, size) * pool->aline; +} + +Pool pool_init(uint32_t size, uint8_t aline) { + Pool pool; + pool.aline = aline; + uint32_t block_size = pool_getBlockIndex_byMemSize(&pool, size); + pool.size = pool_aline(&pool, size); + pool.bitmap = bitmap_init(block_size); + pool.mem = __platform_malloc(pool_aline(&pool, pool.size)); + pool.first_free_block = 0; + pool.purl_free_block_start = 0; + return pool; +} + +void pool_deinit(Pool* pool) { + __platform_free(pool->mem); + pool->mem = NULL; + bitmap_deinit(pool->bitmap); +} + +void* pool_getBytes_byBlockIndex(Pool* pool, uint32_t block_index) { + return pool->mem + block_index * pool->aline; +} + +uint32_t pool_getBlockIndex_byMem(Pool* pool, void* mem) { + uint32_t mem_size = (uintptr_t)mem - (uintptr_t)pool->mem; + return pool_getBlockIndex_byMemSize(pool, mem_size); +} + +void pool_printBlocks(Pool* pool, uint32_t size_min, uint32_t size_max) { + uint32_t block_index_min = pool_getBlockIndex_byMemSize(pool, size_min); + uint32_t block_index_max = pool_getBlockIndex_byMemSize(pool, size_max); + __platform_printf("[bitmap]\r\n"); + uint8_t is_end = 0; + for (uint32_t i = block_index_min; i < block_index_max; i += 16) { + if (is_end) { + break; + } + __platform_printf("0x%x\t: ", i * pool->aline, (i + 15) * pool->aline); + for (uint32_t j = i; j < i + 16; j += 4) { + if (is_end) { + break; + } + for (uint32_t k = j; k < j + 4; k++) { + if (k >= block_index_max) { + is_end = 1; + break; + } + __platform_printf("%d", bitmap_get(pool->bitmap, k)); + } + __platform_printf(" "); + } + __platform_printf("\r\n"); + } +} + +void* pool_malloc(Pool* pool, uint32_t size) { + uint32_t block_index_max = pool_getBlockIndex_byMemSize(pool, pool->size); + uint32_t block_num_need = pool_getBlockIndex_byMemSize(pool, size); + uint32_t block_num_found = 0; + uint8_t found_first_free = 0; + uint32_t block_index; + // if (__is_quick_malloc()) { + // /* high speed malloc */ + // block_index = pool->purl_free_block_start + block_num_need - 1; + // if (block_index < block_index_max) { + // goto found; + // } + // } + + /* low speed malloc */ + for (block_index = pool->first_free_block; + block_index < pool->purl_free_block_start; block_index++) { + /* 8 bit is not free */ + uint8_t bitmap_byte = bitmap_getByte(pool->bitmap, block_index); + if (0xFF == bitmap_byte) { + block_index = 8 * (block_index / 8) + 7; + block_num_found = 0; + continue; + } + /* found a free block */ + if (0 == bitmap_get(pool->bitmap, block_index)) { + /* save the first free */ + if (!found_first_free) { + pool->first_free_block = block_index; + found_first_free = 1; + } + block_num_found++; + } else { + /* a used block appeared, find again */ + block_num_found = 0; + } + /* found all request blocks */ + if (block_num_found >= block_num_need) { + goto found; + } + } + /* malloc for purl free blocks */ + block_index = pool->purl_free_block_start + block_num_need - 1; + if (block_index < block_index_max) { + goto found; + } + + /* no found */ + return NULL; +found: + /* set 1 for found blocks */ + for (uint32_t i = 0; i < block_num_need; i++) { + bitmap_set(pool->bitmap, block_index - i, 1); + } + /* save last used block */ + if (block_index >= pool->purl_free_block_start) { + pool->purl_free_block_start = block_index + 1; + } + /* return mem by block index */ + return pool_getBytes_byBlockIndex(pool, block_index - block_num_need + 1); +} + +void pool_free(Pool* pool, void* mem, uint32_t size) { + uint32_t block_num = pool_getBlockIndex_byMemSize(pool, size); + uint32_t block_index = pool_getBlockIndex_byMem(pool, mem); + for (uint32_t i = 0; i < block_num; i++) { + bitmap_set(pool->bitmap, block_index + i, 0); + } + /* save min free block index to add speed */ + if (block_index < pool->first_free_block) { + pool->first_free_block = block_index; + } + /* save last free block index to add speed */ + uint32_t block_end = block_index + block_num - 1; + if (block_end == pool->purl_free_block_start - 1) { + uint32_t first_pure_free_block = block_index; + /* back to first used block */ + if (0 != first_pure_free_block) { + while (0 == bitmap_get(pool->bitmap, first_pure_free_block - 1)) { + first_pure_free_block--; + if (0 == first_pure_free_block) { + break; + } + } + } + pool->purl_free_block_start = first_pure_free_block; + } + return; +} + +uint32_t aline_by(uint32_t size, uint32_t aline) { + if (size == 0) { + return 0; + } + return ((size - 1) / aline + 1) * aline; +} + +BitMap bitmap_init(uint32_t size) { + BitMap mem_bit_map = + (BitMap)__platform_malloc(((size - 1) / 8 + 1) * sizeof(char)); + if (mem_bit_map == NULL) { + return NULL; + } + uint32_t size_mem_bit_map = (size - 1) / 8 + 1; + __platform_memset(mem_bit_map, 0x0, size_mem_bit_map); + return mem_bit_map; +} + +void bitmap_set(BitMap bitmap, uint32_t index, uint8_t bit) { + uint32_t index_byte = index / 8; + uint8_t index_bit = index % 8; + uint8_t x = (0x1 << index_bit); + /* set 1 */ + if (bit) { + bitmap[index_byte] |= x; + return; + } + /* set 0 */ + bitmap[index_byte] &= ~x; + return; +} + +uint8_t bitmap_getByte(BitMap bitmap, uint32_t index) { + uint32_t index_byte = (index) / 8; + uint8_t byte; + byte = bitmap[index_byte]; + return byte; +} + +uint8_t bitmap_get(BitMap bitmap, uint32_t index) { + uint32_t index_byte = (index) / 8; + uint8_t index_bit = (index) % 8; + uint8_t x = (0x1 << index_bit); + uint8_t bit; + bit = bitmap[index_byte] & x; + return bit > 0 ? 1 : 0; +} + +void bitmap_deinit(BitMap bitmap) { + __platform_free(bitmap); +} diff --git a/port/linux/package/pikascript/pikascript-core/dataMemory.h b/port/linux/package/pikascript/pikascript-core/dataMemory.h new file mode 100644 index 000000000..1b4a026d7 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/dataMemory.h @@ -0,0 +1,68 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __MEMORY_H__ +#define __MEMORY_H__ + +#include "PikaPlatform.h" + +typedef struct { + uint32_t heapUsed; + uint32_t heapUsedMax; +} PikaMemInfo; + +typedef uint8_t* BitMap; + +typedef struct { + BitMap bitmap; + uint8_t* mem; + uint8_t aline; + uint32_t size; + uint32_t first_free_block; + uint32_t purl_free_block_start; +} Pool; + +void pikaFree(void* mem, uint32_t size); +void* pikaMalloc(uint32_t size); +uint16_t pikaMemNow(void); +uint16_t pikaMemMax(void); +void pikaMemMaxReset(void); + +uint32_t aline_by(uint32_t size, uint32_t aline); + +BitMap bitmap_init(uint32_t size); +void bitmap_set(BitMap bitmap, uint32_t index, uint8_t bit); +uint8_t bitmap_get(BitMap bitmap, uint32_t index); +uint8_t bitmap_getByte(BitMap bitmap, uint32_t index); +void bitmap_deinit(BitMap bitmap); + +Pool pool_init(uint32_t size, uint8_t aline); +void* pool_malloc(Pool* pool, uint32_t size); +void pool_free(Pool* pool, void* mem, uint32_t size); +void pool_deinit(Pool* pool); +void pool_printBlocks(Pool* pool, uint32_t block_min, uint32_t block_max); +#endif diff --git a/port/linux/package/pikascript/pikascript-core/dataQueue.c b/port/linux/package/pikascript/pikascript-core/dataQueue.c new file mode 100644 index 000000000..b94dd5b99 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/dataQueue.c @@ -0,0 +1,108 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "dataQueue.h" +#include "PikaPlatform.h" +#include "dataArgs.h" + +void queue_init(Queue* queue) { + args_setInt(queue, "__t", 0); + args_setInt(queue, "__b", 0); +} + +Queue* New_queue(void) { + Args* args = New_args(NULL); + queue_init(args); + return (Queue*)args; +} + +int32_t queue_deinit(Queue* queue) { + Args* args = queue; + args_deinit(args); + return 0; +} + +int32_t queue_pushArg(Queue* queue, Arg* arg) { + Args* args = queue; + uint64_t top = args_getInt(args, "__t"); + /* add top */ + args_setInt(args, "__t", top + 1); + char buff[11]; + arg = arg_setName(arg, fast_itoa(buff, top)); + return args_setArg(args, arg); +} + +Arg* __queue_popArg(Queue* queue, uint8_t is_deinit_arg) { + Args* args = queue; + uint64_t top = args_getInt(args, "__t"); + uint64_t bottom = args_getInt(args, "__b"); + if (top - bottom < 1) { + return NULL; + } + /* add bottom */ + args_setInt(args, "__b", bottom + 1); + char buff[11]; + Arg* res = args_getArg(args, fast_itoa(buff, bottom)); + if (is_deinit_arg) { + args_removeArg(args, res); + } else { + args_removeArg_notDeinitArg(args, res); + } + return res; +} + +Arg* queue_popArg(Queue* queue) { + return __queue_popArg(queue, 1); +} + +Arg* queue_popArg_notDeinitArg(Queue* queue) { + return __queue_popArg(queue, 0); +} + +int32_t queue_pushInt(Queue* queue, int val) { + return queue_pushArg(queue, arg_setInt(NULL, "", val)); +} + +int64_t queue_popInt(Queue* queue) { + return arg_getInt(queue_popArg(queue)); +} + +int32_t queue_pushFloat(Queue* queue, float val) { + return queue_pushArg(queue, arg_setFloat(NULL, "", val)); +} + +float queue_popFloat(Queue* queue) { + return arg_getFloat(queue_popArg(queue)); +} + +int32_t queue_pushStr(Queue* queue, char* str) { + return queue_pushArg(queue, arg_setStr(NULL, "", str)); +} + +char* queue_popStr(Queue* queue) { + return arg_getStr(queue_popArg(queue)); +} diff --git a/port/linux/package/pikascript/pikascript-core/dataQueue.h b/port/linux/package/pikascript/pikascript-core/dataQueue.h new file mode 100644 index 000000000..f67fdf05e --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/dataQueue.h @@ -0,0 +1,49 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __DATA_QUEUE__H +#define __DATA_QUEUE__H +#include "dataArgs.h" + +typedef Args Queue; +Queue* New_queue(void); + +int32_t queue_deinit(Queue* queue); +int32_t queue_pushInt(Queue* queue, int val); +int32_t queue_pushFloat(Queue* queue, float val); +int32_t queue_pushStr(Queue* queue, char* str); +int32_t queue_pushArg(Queue* queue, Arg* arg); +char* fast_itoa(char* buf, uint32_t val); + +int64_t queue_popInt(Queue* queue); +float queue_popFloat(Queue* queue); +char* queue_popStr(Queue* queue); +Arg* queue_popArg(Queue* queue); +Arg* queue_popArg_notDeinitArg(Queue* queue); +int32_t queue_deinit_stack(Queue* queue); +void queue_init(Queue* queue); +#endif diff --git a/port/linux/package/pikascript/pikascript-core/dataQueueObj.c b/port/linux/package/pikascript/pikascript-core/dataQueueObj.c new file mode 100644 index 000000000..d3f84377e --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/dataQueueObj.c @@ -0,0 +1,125 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "dataQueueObj.h" +#include "BaseObj.h" +#include "dataQueue.h" +QueueObj* New_queueObj(void) { + PikaObj* self = New_PikaObj(); + queueObj_init(self); + return self; +} + +int32_t queueObj_init(QueueObj* self) { + obj_setInt(self, "top", 0); + obj_setInt(self, "bottom", 0); + return 0; +} + +int32_t queueObj_pushObj(QueueObj* self, char* className) { + uint64_t top = obj_getInt(self, "top"); + char buff[11]; + char* topStr = fast_itoa(buff, top); + /* add top */ + obj_setInt(self, "top", top + 1); + return obj_newObj(self, topStr, className, New_TinyObj); +} + +PikaObj* queueObj_getCurrentObj(QueueObj* self) { + uint64_t current = obj_getInt(self, "top") - 1; + char buff[11]; + char* currentStr = fast_itoa(buff, current); + return obj_getObj(self, currentStr, 0); +} + +PikaObj* queueObj_popObj(QueueObj* self) { + uint64_t bottom = obj_getInt(self, "bottom"); + char buff[11]; + char* bottomStr = fast_itoa(buff, bottom); + /* add bottom */ + obj_setInt(self, "bottom", bottom + 1); + PikaObj* res = obj_getObj(self, bottomStr, 0); + return res; +} + +int32_t queueObj_pushInt(QueueObj* self, int val) { + uint64_t top = obj_getInt(self, "top"); + char buff[11]; + char* topStr = fast_itoa(buff, top); + /* add top */ + obj_setInt(self, "top", top + 1); + return obj_setInt(self, topStr, val); +} + +int64_t queueObj_popInt(QueueObj* self) { + uint64_t bottom = obj_getInt(self, "bottom"); + char buff[11]; + char* bottomStr = fast_itoa(buff, bottom); + /* add bottom */ + obj_setInt(self, "bottom", bottom + 1); + int64_t res = obj_getInt(self, bottomStr); + obj_removeArg(self, bottomStr); + return res; +} + +int32_t queueObj_pushFloat(QueueObj* self, float val) { + uint64_t top = obj_getInt(self, "top"); + char buff[11]; + char* topStr = fast_itoa(buff, top); + /* add top */ + obj_setInt(self, "top", top + 1); + return obj_setFloat(self, topStr, val); +} + +float queueObj_popFloat(QueueObj* self) { + uint64_t bottom = obj_getInt(self, "bottom"); + char buff[11]; + char* bottomStr = fast_itoa(buff, bottom); + /* add bottom */ + obj_setInt(self, "bottom", bottom + 1); + float res = obj_getFloat(self, bottomStr); + obj_removeArg(self, bottomStr); + return res; +} + +int32_t queueObj_pushStr(QueueObj* self, char* str) { + uint64_t top = obj_getInt(self, "top"); + char buff[11]; + char* topStr = fast_itoa(buff, top); + /* add top */ + obj_setInt(self, "top", top + 1); + return obj_setStr(self, topStr, str); +} + +char* queueObj_popStr(QueueObj* self) { + uint64_t bottom = obj_getInt(self, "bottom"); + char buff[11]; + char* bottomStr = fast_itoa(buff, bottom); + /* add bottom */ + obj_setInt(self, "bottom", bottom + 1); + return obj_getStr(self, bottomStr); +} diff --git a/port/linux/package/pikascript/pikascript-core/dataQueueObj.h b/port/linux/package/pikascript/pikascript-core/dataQueueObj.h new file mode 100644 index 000000000..480e9051a --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/dataQueueObj.h @@ -0,0 +1,48 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __DATA_QUEUE_OBJ__H +#define __DATA_QUEUE_OBJ__H +#include "PikaObj.h" +typedef PikaObj QueueObj; + +QueueObj* New_queueObj(void); +int32_t queueObj_init(QueueObj* self); + +int32_t queueObj_pushInt(QueueObj* self, int val); +int32_t queueObj_pushFloat(QueueObj* self, float val); +int32_t queueObj_pushStr(QueueObj* self, char* str); +int32_t queueObj_pushObj(QueueObj* self, char* className); + +int64_t queueObj_popInt(QueueObj* self); +float queueObj_popFloat(QueueObj* self); +char* queueObj_popStr(QueueObj* self); +PikaObj* queueObj_popObj(QueueObj* self); + +PikaObj* queueObj_getCurrentObj(QueueObj* self); + +#endif diff --git a/port/linux/package/pikascript/pikascript-core/dataStack.c b/port/linux/package/pikascript/pikascript-core/dataStack.c new file mode 100644 index 000000000..6140b0cf0 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/dataStack.c @@ -0,0 +1,112 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "dataStack.h" +#include "dataQueue.h" + +void stack_reset(Stack* stack) { + stack->sp = (uint8_t*)arg_getContent(stack->stack_pyload); + stack->sp_size = (int16_t*)arg_getContent(stack->stack_size_array); + stack->top = 0; +} + +int32_t stack_init(Stack* stack) { + stack->stack_pyload = + arg_setContent(NULL, NULL, PIKA_STACK_BUFF_SIZE); + stack->stack_size_array = + arg_setContent(NULL, NULL, PIKA_STACK_BUFF_SIZE / 4); + stack_reset(stack); + return 0; +}; + +void stack_pushSize(Stack* stack, int16_t size) { + *(stack->sp_size) = size; + stack->sp_size++; +} + +int16_t stack_popSize(Stack* stack) { + stack->sp_size--; + return *(stack->sp_size); +} + +int32_t stack_deinit(Stack* stack) { + arg_deinit(stack->stack_pyload); + arg_deinit(stack->stack_size_array); + return 0; +} + +void stack_pushPyload(Stack* stack, uint8_t* content, size_t size) { + __platform_memcpy(stack->sp, content, size); + stack->sp += size; +} + +uint8_t* stack_popPyload(Stack* stack, size_t size) { + stack->sp -= size; + return stack->sp; +} + +int32_t stack_pushArg(Stack* stack, Arg* arg) { + stack->top++; + size_t size = arg_getTotleSize(arg); + +//! if you unsure about the __impl_pikaMalloc, uncomment this to force alignment +#if PIKA_ARG_ALIGN_ENABLE + /* force alignment to avoid unaligned access */ + size = (size + 4 - 1) & ~(4 - 1); +#endif + + stack_pushSize(stack, size); + stack_pushPyload(stack, arg, size); + arg_deinit(arg); + return 0; +} + +int32_t stack_pushStr(Stack* stack, char* str) { + Arg* newArg = arg_setStr(NULL, "", str); + return stack_pushArg(stack, newArg); +} + +Arg* stack_popArg(Stack* stack) { + if (stack->top == 0) { + return NULL; + } + stack->top--; + int16_t size = stack_popSize(stack); + Arg* res = arg_copy((Arg*)stack_popPyload(stack, size)); + return res; +} + +char* stack_popStr(Stack* stack, char* outBuff) { + Arg* arg = stack_popArg(stack); + strcpy(outBuff, arg_getStr(arg)); + arg_deinit(arg); + return outBuff; +} + +int8_t stack_getTop(Stack* stack) { + return stack->top; +} diff --git a/port/linux/package/pikascript/pikascript-core/dataStack.h b/port/linux/package/pikascript/pikascript-core/dataStack.h new file mode 100644 index 000000000..28e76e3d3 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/dataStack.h @@ -0,0 +1,51 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __DATA_STACK__H +#define __DATA_STACK__H +#include "dataArgs.h" + +typedef struct Stack_t { + Arg* stack_pyload; + Arg* stack_size_array; + uint8_t* sp; + int16_t* sp_size; + int16_t top; +} Stack; + +int32_t stack_deinit(Stack* stack); + +int32_t stack_pushStr(Stack* stack, char* str); +char* stack_popStr(Stack* stack, char* outBuff); +Arg* stack_popArg(Stack* stack); +int32_t stack_pushArg(Stack* stack, Arg* arg); +int8_t stack_getTop(Stack* stack); +int32_t stack_init(Stack* stack); +int16_t stack_popSize(Stack* stack); +void stack_pushSize(Stack* stack, int16_t size); +void stack_reset(Stack* stack); +#endif diff --git a/port/linux/package/pikascript/pikascript-core/dataString.c b/port/linux/package/pikascript/pikascript-core/dataString.c new file mode 100644 index 000000000..020fbc193 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/dataString.c @@ -0,0 +1,326 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "dataString.h" +#include "PikaPlatform.h" + +char* strAppendWithSize_unlimited(char* strOut, char* pData, int32_t Size) { + int32_t strOut_i = strGetSize(strOut); + for (int32_t i = 0; i < Size; i++) { + strOut[strOut_i + i] = pData[i]; + } + strOut_i += Size; + // add \0 to the end of strOut + strOut[strOut_i] = 0; + + return strOut; +} + +char* strCut(char* strOut, char* strIn, char startSign, char endSign) { + int32_t Size = strGetSize(strIn); + int32_t iStart = 0; + int32_t iEnd = Size; + uint8_t isStart = 0; + uint8_t isEnd = 0; + for (int32_t i = 0; i < Size; i++) { + if (strIn[i] == startSign) { + iStart = i; + isStart = 1; + break; + } + } + for (int32_t i = Size - 1; i >= 0; i--) { + if (strIn[i] == endSign) { + iEnd = i; + isEnd = 1; + break; + } + } + int outi = 0; + for (int32_t i = iStart + 1; i < iEnd; i++) { + strOut[outi] = strIn[i]; + outi++; + } + /* add \0 */ + strOut[outi] = 0; + if (isStart && isEnd) { + /* succeed */ + return strOut; + } + /* faild */ + return NULL; +} + +char* strDeleteChar(char* strOut, char* strIn, char ch) { + int32_t iOut = 0; + for (uint32_t i = 0; i < strGetSize(strIn); i++) { + if (ch == strIn[i]) { + continue; + } + strOut[iOut] = strIn[i]; + iOut++; + } + /* add \0 */ + strOut[iOut] = 0; + return strOut; +} + +char* strDeleteEnter(char* str) { + return strDeleteChar(str, str, '\n'); +} + +char* strAppendWithSize(char* strOut, char* pData, int32_t Size) { + int32_t strOut_i = strGetSize(strOut); + for (int32_t i = 0; i < Size; i++) { + strOut[strOut_i + i] = pData[i]; + } + strOut_i += Size; + // add \0 to the end of strOut + strOut[strOut_i] = 0; + + return strOut; +} + +int32_t strCountSign(char* strIn, char sign) { + int32_t count = 0; + for (uint32_t i = 0; i < strGetSize(strIn); i++) { + if (sign == strIn[i]) { + count++; + } + } + return count; +} + +int32_t strGetTokenNum(char* strIn, char sign) { + return strCountSign(strIn, sign) + 1; +} + +uint32_t strGetSize(char* pData) { + return strlen(pData); +} + +char* strAppend_unlimited(char* strOut, char* pData) { + uint32_t Size = 0; + Size = strGetSize(pData); + return strAppendWithSize_unlimited(strOut, pData, Size); +} + +char* strGetLastLine(char* strOut, char* strIn) { + int32_t size = strGetSize(strIn); + char sign = '\n'; + uint32_t beginIndex = 0; + + /* skip the latest '\n' */ + for (int32_t i = size - 2; i > -1; i--) { + if (strIn[i] == sign) { + beginIndex = i + 1; + break; + } + } + + __platform_memcpy(strOut, strIn + beginIndex, size - beginIndex); + strOut[size - beginIndex + 1] = 0; + return strOut; +} + +char* strPointToLastToken(char* strIn, char sign) { + int32_t size = strGetSize(strIn); + for (int32_t i = size - 1; i > -1; i--) { + if (strIn[i] == sign) { + return strIn + i + 1; + } + } + return strIn; +} + +char* strPopLastToken(char* strIn, char sign) { + char* last_token = strPointToLastToken(strIn, sign); + if (last_token != strIn) { + *(last_token - 1) = 0; + } + return last_token; +} + +char* strGetLastToken(char* strOut, char* strIn, char sign) { + int32_t size = strGetSize(strIn); + int32_t buffSize = 0; + for (int32_t i = size - 1; i > -1; i--) { + if (strIn[i] != sign) { + strOut[size - i - 1] = strIn[i]; + buffSize++; + } + if (strIn[i] == sign) { + break; + } + } + int32_t i = 0; + for (i = 0; i < buffSize / 2; i++) { + char buff = strOut[i]; + strOut[i] = strOut[buffSize - i - 1]; + strOut[buffSize - i - 1] = buff; + } + strOut[buffSize] = 0; + return strOut; +} + +char* strPopToken(char* strOut, char* strIn, char sign) { + int32_t getSign = 0; + int32_t iPoped = 0; + int32_t iOut = 0; + int32_t size = strGetSize(strIn); + int32_t i = 0; + for (i = 0; i < size; i++) { + if (getSign) { + strIn[iPoped] = strIn[i]; + iPoped++; + continue; + } + if (strIn[i] != sign) { + strOut[iOut++] = strIn[i]; + continue; + } + if (strIn[i] == sign) { + getSign = 1; + continue; + } + } + strOut[iOut] = 0; + strIn[iPoped] = 0; + return strOut; +} + +char* strGetFirstToken(char* strOut, char* strIn, char sign) { + int32_t size = strGetSize(strIn); + for (int32_t i = 0; i < size; i++) { + if (strIn[i] != sign) { + strOut[i] = strIn[i]; + } + if (strIn[i] == sign) { + break; + } + } + return strOut; +} + +int32_t strGetToken(char* string, char** argv, char sign) { + int32_t argc = 0; + uint32_t i = 0; + // arg_i point32_t to the arg operated now + int32_t arg_i = 0; + // if not found ' ', then put chars from CMD to argv_tem + int32_t char_i = 0; + for (i = 0; i < strGetSize(string); i++) { + if (string[i] != sign) { + argv[arg_i][char_i] = string[i]; + char_i++; + } + if (string[i] == sign) { + // write '\0' to the end of argv + argv[arg_i][char_i] = 0; + arg_i++; + char_i = 0; + } + // write '\0' to the end of last argv + argv[arg_i][char_i] = 0; + } + argc = arg_i + 1; + return argc; +} + +char* strAppend(char* strOut, char* pData) { + uint32_t Size = 0; + Size = strGetSize(pData); + return strAppendWithSize(strOut, pData, Size); +} + +int32_t strIsStartWith(char* str, char* strStart) { + if (NULL == str || NULL == strStart) { + /* input is null */ + return 0; + } + uint32_t size = strGetSize(strStart); + if (0 == strncmp(str, strStart, size)) { + return 1; + } + return 0; +} + +int32_t strEqu(char* str1, char* str2) { + if (NULL == str1 || NULL == str2) { + return 0; + } + return !strcmp(str1, str2); +} + +char* strRemovePrefix(char* inputStr, char* prefix, char* outputStr) { + if (!strIsStartWith(inputStr, prefix)) { + return NULL; + } + + for (uint32_t i = strGetSize(prefix); i < strGetSize(inputStr); i++) { + outputStr[i - strGetSize(prefix)] = inputStr[i]; + } + return outputStr; +} + +char* strClear(char* str) { + for (uint32_t i = 0; i < sizeof(str); i++) { + str[i] = 0; + } + return str; +} + +int32_t strIsContain(char* str, char ch) { + for (uint32_t i = 0; i < strGetSize(str); i++) { + if (str[i] == ch) { + return 1; + } + } + return 0; +} + +char* strCopy(char* strBuff, char* strIn) { + __platform_memcpy(strBuff, strIn, strGetSize(strIn)); + return strBuff; +} + +int32_t strGetLineSize(char* str) { + int i = 0; + while (1) { + if (str[i] == '\n') { + return i; + } + i++; + } +} + +char* strGetLine(char* strOut, char* strIn) { + int32_t lineSize = strGetLineSize(strIn); + __platform_memcpy(strOut, strIn, lineSize); + strOut[lineSize] = 0; + return strOut; +} diff --git a/port/linux/package/pikascript/pikascript-core/dataString.h b/port/linux/package/pikascript/pikascript-core/dataString.h new file mode 100644 index 000000000..3bfbe0c36 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/dataString.h @@ -0,0 +1,64 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __MY_TEST_TOOLS_H +#define __MY_TEST_TOOLS_H +#include "PikaPlatform.h" + +/* size */ +uint32_t strGetSize(char* pData); +/* append */ +char* strAppend(char* strOut, char* pData); +char* strAppend_unlimited(char* strOut, char* pData); +char* strAppendWithSize(char* strOut, char* pData, int32_t Size); +/* cut */ +char* strCut(char* strOut, char* strIn, char startSign, char endSign); +/* assert */ +int32_t strIsStartWith(char* str, char* strStart); +int32_t strEqu(char* str1, char* str2); +/* delete */ +char* strDeleteEnter(char* str); +char* strDeleteChar(char* strOut, char* strIn, char ch); +/* prefix */ +char* strRemovePrefix(char* inputStr, char* prefix, char* outputStr); +/* token */ +int32_t strGetToken(char* string, char** argv, char sign); +char* strPopToken(char* strOut, char* strIn, char sign); +int32_t strCountSign(char* strIn, char sign); +int32_t strGetTokenNum(char* strIn, char sign); +char* strGetFirstToken(char* strOut, char* strIn, char sign); +char* strGetLastToken(char* strOut, char* strIn, char sign); +char* strClear(char* str); +int32_t strIsContain(char* str, char ch); +char* strCopy(char* strBuff, char* strIn); +char* strGetLastLine(char* strOut, char* strIn); +char* strPointToLastToken(char* strIn, char sign); +char* strGetLine(char* strOut, char* strIn); +int32_t strGetLineSize(char* str); +char* strPopLastToken(char* strIn, char sign); + +#endif diff --git a/port/linux/package/pikascript/pikascript-core/dataStrs.c b/port/linux/package/pikascript/pikascript-core/dataStrs.c new file mode 100644 index 000000000..b70060d2b --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/dataStrs.c @@ -0,0 +1,182 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "dataStrs.h" +#include "PikaPlatform.h" +#include "dataString.h" + +Args* New_strBuff(void) { + return New_args(NULL); +} + +char* strsRemovePrefix(Args* buffs_p, char* inputStr, char* prefix) { + int32_t size = strGetSize(inputStr); + char* buff = args_getBuff(buffs_p, size); + return strRemovePrefix(inputStr, prefix, buff); +} + +char* strsGetDirectStr(Args* buffs_p, char* argPath) { + char* directStr = NULL; + directStr = strsCut(buffs_p, argPath, '"', '"'); + if (NULL != directStr) { + return directStr; + } + directStr = strsCut(buffs_p, argPath, '\'', '\''); + if (NULL != directStr) { + return directStr; + } + return NULL; +} + +char* strsAppend(Args* buffs_p, char* strOrigin, char* strToAppend) { + int32_t size = strGetSize(strOrigin) + strGetSize(strToAppend); + char* buff = args_getBuff(buffs_p, size); + char* strOut = strCopy(buff, strOrigin); + strAppend(strOut, strToAppend); + return strOut; +} + +char* strsGetLastToken(Args* buffs_p, char* argPath, char sign) { + int32_t size = strGetSize(argPath); + char* buff = args_getBuff(buffs_p, size); + return strGetLastToken(buff, argPath, sign); +} + +char* strsCut(Args* buffs_p, char* strIn, char startSign, char endSign) { + int32_t size = strGetSize(strIn); + char* buff = args_getBuff(buffs_p, size); + return strCut(buff, strIn, startSign, endSign); +} + +char* strsDeleteChar(Args* buffs_p, char* strIn, char ch) { + int32_t size = strGetSize(strIn); + return strDeleteChar(args_getBuff(buffs_p, size), strIn, ch); +} + +static uint32_t getSizeOfFirstToken(char* str, char sign) { + uint32_t size = strGetSize(str); + for (uint32_t i = 0; i < size; i++) { + if (str[i] == sign) { + return i; + } + } + return size; +} + +char* strsGetFirstToken(Args* buffs_p, char* strIn, char sign) { + int32_t size = getSizeOfFirstToken(strIn, sign); + return strGetFirstToken(args_getBuff(buffs_p, size), strIn, sign); +} + +char* strsPopToken(Args* buffs_p, char* tokens, char sign) { + int32_t size = strGetSize(tokens); + char* buff = args_getBuff(buffs_p, size); + return strPopToken(buff, tokens, sign); +} + +char* strsCopy(Args* buffs_p, char* source) { + int32_t size = strGetSize(source); + char* buff = args_getBuff(buffs_p, size); + return strCopy(buff, source); +} + +char* strsFormat(Args* buffs_p, uint16_t buffSize, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + char* res = args_getBuff(buffs_p, buffSize); + __platform_vsnprintf(res, buffSize, fmt, args); + va_end(args); + return res; +} + +Arg* arg_strAppend(Arg* arg_in, char* str_to_append) { + Args buffs = {0}; + char* str_out = strsAppend(&buffs, arg_getStr(arg_in), str_to_append); + Arg* arg_out = arg_setStr(arg_in, "", str_out); + arg_deinit(arg_in); + strsDeinit(&buffs); + return arg_out; +} + +char* strsReplace(Args* buffs_p, char* orig, char* rep, char* with) { + char* result; // the return string + char* ins; // the next insert point + char* tmp; // varies + int len_rep; // length of rep (the string to remove) + int len_with; // length of with (the string to replace rep with) + int len_front; // distance between rep and end of last rep + int count; // number of replacements + + // sanity checks and initialization + if (!orig || !rep) + return NULL; + len_rep = strlen(rep); + if (len_rep == 0) + return NULL; // empty rep causes infinite loop during count + if (!with) + with = ""; + len_with = strlen(with); + // count the number of replacements needed + ins = orig; + tmp = strstr(ins, rep); + count = 0; + while (tmp) { + count++; + ins = tmp + len_rep; + tmp = strstr(ins, rep); + } + tmp = + args_getBuff(buffs_p, strlen(orig) + (len_with - len_rep) * count + 1); + result = tmp; + if (NULL == result) { + return NULL; + } + // first time through the loop, all the variable are set correctly + // from here on, + // tmp points to the end of the result string + // ins points to the next occurrence of rep in orig + // orig points to the remainder of orig after "end of rep" + while (count--) { + ins = strstr(orig, rep); + len_front = ins - orig; + tmp = strncpy(tmp, orig, len_front) + len_front; + tmp = strcpy(tmp, with) + len_with; + orig += len_front + len_rep; // move to next "end of rep" + } + strcpy(tmp, orig); + return result; +} + +char* strsGetLine(Args* buffs_p, char* code) { + int32_t lineSize = strGetLineSize(code); + char* line_buff = args_getBuff(buffs_p, lineSize + 1); + return strGetLine(line_buff, code); +} + +void strsDeinit(Args* buffs_p) { + link_deinit_stack(buffs_p); +} diff --git a/port/linux/package/pikascript/pikascript-core/dataStrs.h b/port/linux/package/pikascript/pikascript-core/dataStrs.h new file mode 100644 index 000000000..40e369055 --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/dataStrs.h @@ -0,0 +1,46 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __STR_ARGS__H +#define __STR_ARGS__H +#include "dataArgs.h" +Args* New_strBuff(void); +char* strsGetFirstToken(Args* buffs, char* strIn, char sign); +char* strsGetLastToken(Args* buffs, char* arg_Path, char sign); +char* strsPopToken(Args* buffs, char* tokens, char sign); +char* strsCopy(Args* buffs, char* source); +char* strsDeleteChar(Args* buff, char* strIn, char ch); +char* strsCut(Args* buffs, char* strIn, char startSign, char endSign); +char* strsRemovePrefix(Args* buffs, char* inputStr, char* prefix); +char* strsAppend(Args* buffs, char* strOrigin, char* strAppend); +char* strsFormat(Args* buffs, uint16_t buffSize, const char* fmt, ...); +char* strsGetDirectStr(Args* buffs, char* argPath); +Arg* arg_strAppend(Arg* arg_in, char* str_to_append); +char* strsReplace(Args* buffs, char* orig, char* rep, char* with); +char* strsGetLine(Args* buffs, char* code); +void strsDeinit(Args* buffs); +#endif diff --git a/port/linux/package/pikascript/pikascript-core/pika_config_valid.h b/port/linux/package/pikascript/pikascript-core/pika_config_valid.h new file mode 100644 index 000000000..7dc15c55d --- /dev/null +++ b/port/linux/package/pikascript/pikascript-core/pika_config_valid.h @@ -0,0 +1,67 @@ +/* + * This file is part of the PikaScript project. + * http://github.com/pikastech/pikascript + * + * MIT License + * + * Copyright (c) 2021 lyon 李昂 liang6516@outlook.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __PIKA_CFG_VALID_H__ +#define __PIKA_CFG_VALID_H__ + + /* default configuration */ + #define PIKA_LINE_BUFF_SIZE 128 + #define PIKA_SPRINTF_BUFF_SIZE 128 + #define PIKA_STACK_BUFF_SIZE 256 + #define PIKA_NAME_BUFF_SIZE 32 + #define PIKA_PATH_BUFF_SIZE 64 + #define PIKA_BYTES_DEFAULT_SIZE 64 + #define PIKA_ARG_ALIGN_ENABLE 1 + #define PIKA_METHOD_CACHE_ENABLE 0 + #define PIKA_BUILTIN_LIST_ENABLE 0 + #define PIKA_BUILTIN_DICT_ENABLE 0 + + /* optimize options */ + #define PIKA_OPTIMIZE_SIZE 0 + #define PIKA_OPTIMIZE_SPEED 1 + + /* default optimize */ + #define PIKA_OPTIMIZE PIKA_OPTIMIZE_SIZE + + /* use user config */ + #ifdef PIKA_CONFIG_ENABLE + #include "pika_config.h" + #endif + + /* config for size optimize */ + #if PIKA_OPTIMIZE == PIKA_OPTIMIZE_SIZE + #undef PIKA_METHOD_CACHE_ENABLE + #define PIKA_METHOD_CACHE_ENABLE 0 + + /* config for speed optimize */ + #elif PIKA_OPTIMIZE == PIKA_OPTIMIZE_SPEED + #undef PIKA_METHOD_CACHE_ENABLE + #define PIKA_METHOD_CACHE_ENABLE 1 + #endif + + /* configuration validation */ + +#endif