From 0fef360caf43278c6536e08312a1a0f876581674 Mon Sep 17 00:00:00 2001 From: "S. Mahmudul Hasan" Date: Tue, 3 Oct 2023 13:45:21 -0400 Subject: [PATCH 01/28] Added better string formatting as required by Issue#138 --- python/builtins.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/python/builtins.py b/python/builtins.py index 4abb8187..19193a58 100644 --- a/python/builtins.py +++ b/python/builtins.py @@ -96,13 +96,20 @@ def sorted(iterable, reverse=False, key=None): return a ##### str ##### -def __f(self, *args): +def __f(self, *args, **kwargs): if '{}' in self: for i in range(len(args)): self = self.replace('{}', str(args[i]), 1) else: - for i in range(len(args)): - self = self.replace('{'+str(i)+'}', str(args[i])) + # Positional arguments will be followed by keyword arguments + # 1. Replace the positional arguments + for i,a in enumerate(args): + self = self.replace('{'+str(i)+'}', str(a)) + + # 2. Replace the keyword arguments + for k,v in kwargs.items(): + self = self.replace('{'+k+'}', str(v)) + return self str.format = __f From c18821fc42f056378174c70017ab68b8c2558b99 Mon Sep 17 00:00:00 2001 From: Non <43197300+nonperforming@users.noreply.github.com> Date: Thu, 5 Oct 2023 19:16:40 +1300 Subject: [PATCH 02/28] Powershell-ify build.ps1 Convert *nix commands to PowerShell commands --- build.ps1 | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/build.ps1 b/build.ps1 index 3b794a76..af980cfe 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,9 +1,12 @@ if (Test-Path build) { Remove-Item -Recurse -Force build } -mkdir build -cd build + +New-Item -ItemType Directory -Path build +Push-Location build + cmake .. cmake --build . --config Release -cp Release/main.exe ../ -cp Release/pocketpy.dll ../ \ No newline at end of file + +Copy-Item "Release\main.exe" -Destination ".." # Note: NTFS uses backslash (\) instead of slashes (*nix, /) +Copy-Item "Release\pocketpy.dll" -Destination ".." From 63bf13aac245b2b68f4238e89b865364f3841997 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Fri, 6 Oct 2023 00:58:08 +0800 Subject: [PATCH 03/28] some minor change --- build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sh b/build.sh index 00290fe2..ff84b5dc 100644 --- a/build.sh +++ b/build.sh @@ -45,7 +45,7 @@ echo "> Compiling main.cpp and linking to libpocketpy$LIB_EXTENSION..." clang++ $FLAGS -o main src2/main.cpp -L. -lpocketpy $LINK_FLAGS if [ $? -eq 0 ]; then - echo "Build completed successfully. To use pocketpy, run : ./main" + echo "Build completed. Type \"./main\" to enter REPL." else echo "Build failed." exit 1 From 52c58ec87f44789a76b374bddb19a98b589f0db5 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Fri, 6 Oct 2023 01:13:19 +0800 Subject: [PATCH 04/28] Update 70_math.py --- tests/70_math.py | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/tests/70_math.py b/tests/70_math.py index 0545aabc..4dbcce67 100644 --- a/tests/70_math.py +++ b/tests/70_math.py @@ -25,4 +25,34 @@ assert floor(-1.2) == -2 assert ceil(1.2) == 2 assert ceil(-1.2) == -1 -assert isclose(sqrt(4), 2.0) \ No newline at end of file +assert isclose(sqrt(4), 2.0) + +import math + +# test fsum +assert math.fsum([0.1] * 10) == 1.0 + +# test gcd +assert math.gcd(10, 5) == 5 +assert math.gcd(10, 6) == 2 +assert math.gcd(10, 7) == 1 +assert math.gcd(10, 10) == 10 +assert math.gcd(-10, 10) == 10 + +# test modf +x, y = math.modf(1.5) +assert isclose(x, 0.5) +assert isclose(y, 1.0) + +x, y = math.modf(-1.5) +assert isclose(x, -0.5) +assert isclose(y, -1.0) + +# test factorial +assert math.factorial(0) == 1 +assert math.factorial(1) == 1 +assert math.factorial(2) == 2 +assert math.factorial(3) == 6 +assert math.factorial(4) == 24 +assert math.factorial(5) == 120 + From 5b42930ede1612af217e5ec52f98185b554d9172 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Fri, 6 Oct 2023 01:25:22 +0800 Subject: [PATCH 05/28] ... --- CMakeLists.txt | 6 +++--- build.sh | 6 ++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f05b5b5..1587d222 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,13 +27,13 @@ endif() if(EMSCRIPTEN) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions") - set(CMAKE_CXX_FLAGS_RELEASE "-O3") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3") elseif(MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc /utf-8") - set(CMAKE_CXX_FLAGS_RELEASE "/O2") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /O2") else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions") - set(CMAKE_CXX_FLAGS_RELEASE "-O2") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2") endif() include_directories(${CMAKE_CURRENT_LIST_DIR}/include) diff --git a/build.sh b/build.sh index ff84b5dc..473b1f7d 100644 --- a/build.sh +++ b/build.sh @@ -21,13 +21,11 @@ echo "> Running prebuild.py... " python3 prebuild.py -# echo -n "Finding source files... " SRC=$(find src/ -name "*.cpp") -# echo "Done" echo "> Compiling and linking source files... " -FLAGS="-std=c++17 -O2 -stdlib=libc++ -Wfatal-errors -Iinclude" +FLAGS="-std=c++17 -O1 -stdlib=libc++ -Wfatal-errors -Iinclude" if [[ "$OSTYPE" == "darwin"* ]]; then LIB_EXTENSION=".dylib" FLAGS="$FLAGS -undefined dynamic_lookup" @@ -42,7 +40,7 @@ clang++ $FLAGS -o libpocketpy$LIB_EXTENSION $SRC -fPIC -shared -ldl # compile main.cpp and link to libpocketpy.so echo "> Compiling main.cpp and linking to libpocketpy$LIB_EXTENSION..." -clang++ $FLAGS -o main src2/main.cpp -L. -lpocketpy $LINK_FLAGS +clang++ $FLAGS -o main -O1 src2/main.cpp -L. -lpocketpy $LINK_FLAGS if [ $? -eq 0 ]; then echo "Build completed. Type \"./main\" to enter REPL." From 59b1c13f354b7b819a16b2f94b9bda8b428fd710 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Fri, 6 Oct 2023 01:30:20 +0800 Subject: [PATCH 06/28] Update CMakeLists.txt --- CMakeLists.txt | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1587d222..67a0e8a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,19 +21,12 @@ if(NOT ${PREBUILD_RESULT} EQUAL 0) message(FATAL_ERROR "prebuild.py: ${PREBUILD_RESULT}") endif() -if(MSVC) - add_compile_options("/utf-8") -endif() - if(EMSCRIPTEN) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions -O3") elseif(MSVC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc /utf-8") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /O2") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc /utf-8 /O2") else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions -O2") endif() include_directories(${CMAKE_CURRENT_LIST_DIR}/include) From ee548164218d0f1c22759d6d6cd7ca5e42f297b8 Mon Sep 17 00:00:00 2001 From: "S. Mahmudul Hasan" Date: Thu, 5 Oct 2023 20:04:21 -0400 Subject: [PATCH 07/28] Updated str.format to tokenization-based-replacement operation --- python/builtins.py | 119 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 105 insertions(+), 14 deletions(-) diff --git a/python/builtins.py b/python/builtins.py index 19193a58..1f096cc1 100644 --- a/python/builtins.py +++ b/python/builtins.py @@ -96,21 +96,112 @@ def sorted(iterable, reverse=False, key=None): return a ##### str ##### -def __f(self, *args, **kwargs): - if '{}' in self: - for i in range(len(args)): - self = self.replace('{}', str(args[i]), 1) - else: - # Positional arguments will be followed by keyword arguments - # 1. Replace the positional arguments - for i,a in enumerate(args): - self = self.replace('{'+str(i)+'}', str(a)) - - # 2. Replace the keyword arguments - for k,v in kwargs.items(): - self = self.replace('{'+k+'}', str(v)) +def tokenize(s:str) -> list: + tokens = [] + L, R = 0,0 - return self + mode = None + curPos = 0 + lookingForKword = False + + while(R str: + tokens = tokenize(self) + argMap = {} + for i, a in enumerate(args): + argMap[str(i)] = a + final_tokens = [] + for t in tokens: + if t[0] == '{' and t[-1] == '}': + key = t[1:-1] + argMapVal = argMap.get(key, None) + kwargsVal = kwargs.get(key, None) + + if argMapVal is None and kwargsVal is None: + raise ValueError("No arg found for token: "+t) + elif argMapVal is not None: + final_tokens.append(str(argMapVal)) + else: + final_tokens.append(str(kwargsVal)) + else: + final_tokens.append(t) + + return ''.join(final_tokens) + + # if '{}' in self: + # for i in range(len(args)): + # self = self.replace('{}', str(args[i]), 1) + # else: + # # Positional arguments will be followed by keyword arguments + # # 1. Replace the positional arguments + # for i,a in enumerate(args): + # self = self.replace('{'+str(i)+'}', str(a)) + + # # 2. Replace the keyword arguments + # for k,v in kwargs.items(): + # self = self.replace('{'+k+'}', str(v)) + + # return self str.format = __f def __f(self, chars=None): From 151e9467ae717c0dd9acc4fcfb5adbe24fed3279 Mon Sep 17 00:00:00 2001 From: "S. Mahmudul Hasan" Date: Fri, 6 Oct 2023 16:56:19 -0400 Subject: [PATCH 08/28] fixed the error case for escaped curly braces, and converted the tokenize function into a inner function --- python/builtins.py | 161 +++++++++++++++++++++++++-------------------- 1 file changed, 89 insertions(+), 72 deletions(-) diff --git a/python/builtins.py b/python/builtins.py index 1f096cc1..9528160b 100644 --- a/python/builtins.py +++ b/python/builtins.py @@ -96,77 +96,94 @@ def sorted(iterable, reverse=False, key=None): return a ##### str ##### -def tokenize(s:str) -> list: - tokens = [] - L, R = 0,0 - - mode = None - curPos = 0 - lookingForKword = False - - while(R str: - tokens = tokenize(self) + def tokenizeString(s:str): + tokens = [] + L, R = 0,0 + + mode = None + curArg = 0 + # lookingForKword = False + + while(R str: key = t[1:-1] argMapVal = argMap.get(key, None) kwargsVal = kwargs.get(key, None) - + if argMapVal is None and kwargsVal is None: raise ValueError("No arg found for token: "+t) elif argMapVal is not None: @@ -187,7 +204,7 @@ def __f(self:str, *args, **kwargs) -> str: final_tokens.append(t) return ''.join(final_tokens) - + # if '{}' in self: # for i in range(len(args)): # self = self.replace('{}', str(args[i]), 1) From 2f525617090d57274c7fcf615f5ea76938d7444e Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sat, 7 Oct 2023 11:37:36 +0800 Subject: [PATCH 09/28] add more json test cases --- tests/80_json.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/80_json.py b/tests/80_json.py index d821ab92..1e0f1ccc 100644 --- a/tests/80_json.py +++ b/tests/80_json.py @@ -16,6 +16,15 @@ a = { import json +assert json.loads("1") == 1 +assert json.loads('"1"') == "1" +assert json.loads("0.0") == 0.0 +assert json.loads("[1, 2]") == [1, 2] +assert json.loads("null") == None +assert json.loads("true") == True +assert json.loads("false") == False +assert json.loads("{}") == {} + _j = json.dumps(a) _a = json.loads(_j) From 098b85f89b90dfbd15e24fbc83dc181951d58263 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sat, 7 Oct 2023 11:55:57 +0800 Subject: [PATCH 10/28] ... --- python/builtins.py | 18 ++---------------- tests/04_str.py | 13 +++++++++++++ 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/python/builtins.py b/python/builtins.py index 9528160b..436cd39c 100644 --- a/python/builtins.py +++ b/python/builtins.py @@ -96,8 +96,8 @@ def sorted(iterable, reverse=False, key=None): return a ##### str ##### -def __f(self:str, *args, **kwargs) -> str: - def tokenizeString(s:str): +def __f(self: str, *args, **kwargs) -> str: + def tokenizeString(s: str): tokens = [] L, R = 0,0 @@ -205,20 +205,6 @@ def __f(self:str, *args, **kwargs) -> str: return ''.join(final_tokens) - # if '{}' in self: - # for i in range(len(args)): - # self = self.replace('{}', str(args[i]), 1) - # else: - # # Positional arguments will be followed by keyword arguments - # # 1. Replace the positional arguments - # for i,a in enumerate(args): - # self = self.replace('{'+str(i)+'}', str(a)) - - # # 2. Replace the keyword arguments - # for k,v in kwargs.items(): - # self = self.replace('{'+k+'}', str(v)) - - # return self str.format = __f def __f(self, chars=None): diff --git a/tests/04_str.py b/tests/04_str.py index dd4a1587..6a2e1a44 100644 --- a/tests/04_str.py +++ b/tests/04_str.py @@ -97,6 +97,19 @@ assert "{0} {1} {2}".format("I", "love", "Python") == "I love Python" assert "{2} {1} {0}".format("I", "love", "Python") == "Python love I" assert "{0}{1}{0}".format("abra", "cad") == "abracadabra" +assert "{k}={v}".format(k="key", v="value") == "key=value" +assert "{k}={k}".format(k="key") == "key=key" +assert "{0}={1}".format('{0}', '{1}') == "{0}={1}" +assert "{{{0}}}".format(1) == "{1}" +assert "{0}{1}{1}".format(1, 2, 3) == "122" +try: + "{0}={1}}".format(1, 2) + exit(1) +except ValueError: + pass +assert "{{{}xxx{}x}}".format(1, 2) == "{1xxx2x}" +assert "{{abc}}".format() == "{abc}" + # 3rd slice a = "Hello, World!" assert a[::-1] == "!dlroW ,olleH" From 7312afdad24bb308037088d34b32ed0078fed7d2 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sat, 7 Oct 2023 13:28:20 +0800 Subject: [PATCH 11/28] fix a term --- README.md | 2 +- README_zh.md | 2 +- docs/index.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f0063c8d..18095dd3 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ These platforms are officially tested. + Android 64-bit / 32-bit + iOS 64-bit + Emscripten 32-bit -+ Raspberry Pi 64-bit ++ Raspberry Pi OS 64-bit ## Quick Start diff --git a/README_zh.md b/README_zh.md index 9e1394b8..7a6f33b6 100644 --- a/README_zh.md +++ b/README_zh.md @@ -27,7 +27,7 @@ pkpy 支持任何拥有 C++17 编译器的平台。 + Android 64-bit / 32-bit + iOS 64-bit + Emscripten 32-bit -+ Raspberry Pi 64-bit ++ Raspberry Pi OS 64-bit ## 快速上手 diff --git a/docs/index.md b/docs/index.md index 673dc2ee..08ed87c3 100644 --- a/docs/index.md +++ b/docs/index.md @@ -39,7 +39,7 @@ These platforms are officially tested. + Android 64-bit / 32-bit + iOS 64-bit + Emscripten 32-bit -+ Raspberry Pi 64-bit ++ Raspberry Pi OS 64-bit ## Sponsor me From b29801bbe8dc03ceca3475a828dd6143585b8887 Mon Sep 17 00:00:00 2001 From: Non <43197300+nonperforming@users.noreply.github.com> Date: Sun, 8 Oct 2023 00:11:20 +1300 Subject: [PATCH 12/28] Use emojis in feature list --- README.md | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 18095dd3..027bd9ed 100644 --- a/README.md +++ b/README.md @@ -114,26 +114,26 @@ for a quick overview of the supported features. | Name | Example | Supported | | --------------- | ------------------------------- | --------- | -| If Else | `if..else..elif` | YES | -| Loop | `for/while/break/continue` | YES | -| Function | `def f(x,*args,y=1):` | YES | -| Subclass | `class A(B):` | YES | -| List | `[1, 2, 'a']` | YES | -| ListComp | `[i for i in range(5)]` | YES | -| Slice | `a[1:2], a[:2], a[1:]` | YES | -| Tuple | `(1, 2, 'a')` | YES | -| Dict | `{'a': 1, 'b': 2}` | YES | -| F-String | `f'value is {x}'` | YES | -| Unpacking | `a, b = 1, 2` | YES | -| Star Unpacking | `a, *b = [1, 2, 3]` | YES | -| Exception | `raise/try..catch` | YES | -| Dynamic Code | `eval()/exec()` | YES | -| Reflection | `hasattr()/getattr()/setattr()` | YES | -| Import | `import/from..import` | YES | -| Context Block | `with as :` | YES | -| Type Annotation | `def f(a:int, b:float=1)` | YES | -| Generator | `yield i` | YES | -| Decorator | `@cache` | YES | +| If Else | `if..else..elif` | ✅ | +| Loop | `for/while/break/continue` | ✅ | +| Function | `def f(x,*args,y=1):` | ✅ | +| Subclass | `class A(B):` | ✅ | +| List | `[1, 2, 'a']` | ✅ | +| ListComp | `[i for i in range(5)]` | ✅ | +| Slice | `a[1:2], a[:2], a[1:]` | ✅ | +| Tuple | `(1, 2, 'a')` | ✅ | +| Dict | `{'a': 1, 'b': 2}` | ✅ | +| F-String | `f'value is {x}'` | ✅ | +| Unpacking | `a, b = 1, 2` | ✅ | +| Star Unpacking | `a, *b = [1, 2, 3]` | ✅ | +| Exception | `raise/try..catch` | ✅ | +| Dynamic Code | `eval()/exec()` | ✅ | +| Reflection | `hasattr()/getattr()/setattr()` | ✅ | +| Import | `import/from..import` | ✅ | +| Context Block | `with as :` | ✅ | +| Type Annotation | `def f(a:int, b:float=1)` | ✅ | +| Generator | `yield i` | ✅ | +| Decorator | `@cache` | ✅ | ## Contribution From 2b72428931fda01a8d58bec46137a9fa1c46960c Mon Sep 17 00:00:00 2001 From: Non <43197300+nonperforming@users.noreply.github.com> Date: Sun, 8 Oct 2023 00:13:25 +1300 Subject: [PATCH 13/28] Use emojis in feature list (zh) --- README_zh.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/README_zh.md b/README_zh.md index 7a6f33b6..007ab2f4 100644 --- a/README_zh.md +++ b/README_zh.md @@ -76,25 +76,25 @@ int main(){ | 特性 | 示例 | 支持 | | ------------ | ------------------------------- | ---- | -| 分支 | `if..else..elif` | YES | -| 循环 | `for/while/break/continue` | YES | -| 函数 | `def f(x,*args,y=1):` | YES | -| 类与继承 | `class A(B):` | YES | -| 列表 | `[1, 2, 'a']` | YES | -| 列表生成式 | `[i for i in range(5)]` | YES | -| 切片 | `a[1:2], a[:2], a[1:]` | YES | -| 元组 | `(1, 2, 'a')` | YES | -| 字典 | `{'a': 1, 'b': 2}` | YES | -| 格式化字符串 | `f'value is {x}'` | YES | -| 序列解包 | `a, b = 1, 2` | YES | -| 异常 | `raise/try..catch` | YES | -| 动态分发 | `eval()/exec()` | YES | -| 反射 | `hasattr()/getattr()/setattr()` | YES | -| 导入模块 | `import/from..import` | YES | -| 上下文管理器 | `with as :` | YES | -| 类型标注 | `def f(a:int, b:float=1)` | YES | -| 生成器 | `yield i` | YES | -| 装饰器 | `@cache` | YES | +| 分支 | `if..else..elif` | ✅ | +| 循环 | `for/while/break/continue` | ✅ | +| 函数 | `def f(x,*args,y=1):` | ✅ | +| 类与继承 | `class A(B):` | ✅ | +| 列表 | `[1, 2, 'a']` | ✅ | +| 列表生成式 | `[i for i in range(5)]` | ✅ | +| 切片 | `a[1:2], a[:2], a[1:]` | ✅ | +| 元组 | `(1, 2, 'a')` | ✅ | +| 字典 | `{'a': 1, 'b': 2}` | ✅ | +| 格式化字符串 | `f'value is {x}'` | ✅ | +| 序列解包 | `a, b = 1, 2` | ✅ | +| 异常 | `raise/try..catch` | ✅ | +| 动态分发 | `eval()/exec()` | ✅ | +| 反射 | `hasattr()/getattr()/setattr()` | ✅ | +| 导入模块 | `import/from..import` | ✅ | +| 上下文管理器 | `with as :` | ✅ | +| 类型标注 | `def f(a:int, b:float=1)` | ✅ | +| 生成器 | `yield i` | ✅ | +| 装饰器 | `@cache` | ✅ | ## 参考 From 85eefaab5d4805de4e6eb008737a023e271e0298 Mon Sep 17 00:00:00 2001 From: Non <43197300+nonperforming@users.noreply.github.com> Date: Sun, 8 Oct 2023 00:20:51 +1300 Subject: [PATCH 14/28] Do not compile on docs change --- .github/workflows/main.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 99bddbf9..4b48e6f2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,5 +1,15 @@ name: build -on: [push, pull_request] +on: + push: + paths-ignore: + - 'docs/**' + - 'web/**' + - '**.md' + pull_request: + paths-ignore: + - 'docs/**' + - 'web/**' + - '**.md' jobs: build_win: runs-on: windows-latest From 4df6d4fdb1689734064c94b3e9ee9ae8b88fab15 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 8 Oct 2023 01:36:11 +0800 Subject: [PATCH 15/28] fix a bug of `traceback` --- src/ceval.cpp | 6 ------ src/vm.cpp | 18 +++++++++++++----- tests/80_traceback.py | 8 ++++++-- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/ceval.cpp b/src/ceval.cpp index e867f2cd..bd867b2b 100644 --- a/src/ceval.cpp +++ b/src/ceval.cpp @@ -760,12 +760,6 @@ __NEXT_STEP:; PK_UNUSED(e); PyObject* obj = POPX(); Exception& _e = CAST(Exception&, obj); - int actual_ip = frame->_ip; - if(_e._ip_on_error >= 0 && _e._code_on_error == (void*)frame->co) actual_ip = _e._ip_on_error; - int current_line = frame->co->lines[actual_ip]; // current line - auto current_f_name = frame->co->name.sv(); // current function name - if(frame->_callable == nullptr) current_f_name = ""; // not in a function - _e.st_push(frame->co->src->snapshot(current_line, nullptr, current_f_name)); _pop_frame(); if(callstack.empty()){ #if PK_DEBUG_FULL_EXCEPTION diff --git a/src/vm.cpp b/src/vm.cpp index 5a016938..5ee9913d 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -1082,13 +1082,21 @@ void VM::_error(Exception e){ } void VM::_raise(bool re_raise){ - Frame* top = top_frame().get(); + Frame* frame = top_frame().get(); + Exception& e = PK_OBJ_GET(Exception, s_data.top()); if(!re_raise){ - Exception& e = PK_OBJ_GET(Exception, s_data.top()); - e._ip_on_error = top->_ip; - e._code_on_error = (void*)top->co; + e._ip_on_error = frame->_ip; + e._code_on_error = (void*)frame->co; } - bool ok = top->jump_to_exception_handler(); + bool ok = frame->jump_to_exception_handler(); + + int actual_ip = frame->_ip; + if(e._ip_on_error >= 0 && e._code_on_error == (void*)frame->co) actual_ip = e._ip_on_error; + int current_line = frame->co->lines[actual_ip]; // current line + auto current_f_name = frame->co->name.sv(); // current function name + if(frame->_callable == nullptr) current_f_name = ""; // not in a function + e.st_push(frame->co->src->snapshot(current_line, nullptr, current_f_name)); + if(ok) throw HandledException(); else throw UnhandledException(); } diff --git a/tests/80_traceback.py b/tests/80_traceback.py index 25fbfec7..b1df66fd 100644 --- a/tests/80_traceback.py +++ b/tests/80_traceback.py @@ -6,5 +6,9 @@ try: except KeyError: s = traceback.format_exc() -assert s == r'''Traceback (most recent call last): -KeyError: 6''' \ No newline at end of file +ok = s == '''Traceback (most recent call last): + File "80_traceback.py", line 5 + b = a[6] +KeyError: 6''' + +assert ok, s \ No newline at end of file From 9c5d231fb6614cb523a14e83b6fcdd5420edfe8c Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 8 Oct 2023 11:33:12 +0800 Subject: [PATCH 16/28] fix a broken link --- docs/bindings.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/bindings.md b/docs/bindings.md index 33968d5c..328b3c28 100644 --- a/docs/bindings.md +++ b/docs/bindings.md @@ -160,4 +160,4 @@ For example, `vm->bind__add__` is preferred over `vm->bind_method<1>(type, "__ad ### Further reading -See [linalg.h](https://github.com/blueloveTH/pocketpy/blob/main/src/linalg.h) for a complete example used by `linalg` module. \ No newline at end of file +See [linalg.h](https://github.com/blueloveTH/pocketpy/blob/main/src/random.cpp) for a complete example used by `random` module. \ No newline at end of file From 9a17085b875085c40d8799fca03f03253c7a00eb Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 8 Oct 2023 11:45:42 +0800 Subject: [PATCH 17/28] fix a doc issue to add `/utf-8` on MSVC --- README.md | 1 + docs/quick-start/installation.md | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 027bd9ed..ebce1fe3 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ To compile it with your project, these flags must be set: + `--std=c++17` flag must be set + Exception must be enabled ++ For MSVC, `/utf-8` flag must be set For development build on Linux, use this snippet. ```bash diff --git a/docs/quick-start/installation.md b/docs/quick-start/installation.md index 4332c228..9a0f4f38 100644 --- a/docs/quick-start/installation.md +++ b/docs/quick-start/installation.md @@ -43,6 +43,7 @@ To compile it with your project, these flags must be set: + `--std=c++17` flag must be set + Exception must be enabled ++ For MSVC, `/utf-8` flag must be set For emscripten, you must enable exceptions to make pocketpy work properly. See https://emscripten.org/docs/porting/exceptions.html. From 3478ddeeb0764acfd8975e73f4287891e76d3179 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 8 Oct 2023 11:59:01 +0800 Subject: [PATCH 18/28] change `clang++` into `clang` --- README.md | 2 +- build.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ebce1fe3..bb9875f6 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ To compile it with your project, these flags must be set: For development build on Linux, use this snippet. ```bash # prerequisites -sudo apt-get install libc++-dev libc++abi-dev clang++ +sudo apt-get install libc++-dev libc++abi-dev clang # build the repo bash build.sh # unittest diff --git a/build.sh b/build.sh index 473b1f7d..0a2303f4 100644 --- a/build.sh +++ b/build.sh @@ -10,7 +10,7 @@ fi # Check if clang++ is installed if ! type -P clang++ >/dev/null 2>&1; then echo "clang++ is required and not installed. Kindly install it." - echo "Run: sudo apt-get install libc++-dev libc++abi-dev clang++" + echo "Run: sudo apt-get install libc++-dev libc++abi-dev clang" exit 1 fi From 5bbb534b2028ae6d3251711b8125a6afb255ca01 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 8 Oct 2023 16:08:29 +0800 Subject: [PATCH 19/28] ... --- docs/bindings.md | 59 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/docs/bindings.md b/docs/bindings.md index 328b3c28..3fd78614 100644 --- a/docs/bindings.md +++ b/docs/bindings.md @@ -49,6 +49,65 @@ vm->bind(obj, }); ``` +#### How to capture something + +By default, the lambda being bound is a C function pointer, +you cannot capture anything! The following example does not compile. + +```cpp +int x = 1; +vm->bind(obj, "f() -> int", [x](VM* vm, ArgsView args){ + // error: cannot capture 'x' + return py_var(vm, x); +}); +``` + +I do not encourage you to capture something in a lambda being bound +because: +1. Captured lambda runs slower and causes "code-bloat". +2. Captured values are unsafe, especially for `PyObject*` as they could leak by accident. + +However, there are 3 ways to capture something when you really need to. +The most safe and elegant way is to subclass `VM` and add a member variable. + +```cpp +class YourVM : public VM{ +public: + int x; + YourVM() : VM() {} +}; + +int main(){ + YourVM* vm = new YourVM(); + vm->x = 1; + vm->bind(obj, "f() -> int", [](VM* _vm, ArgsView args){ + // do a static_cast and you can get any extra members of YourVM + YourVM* vm = static_cast(_vm); + return py_var(vm, vm->x); + }); + return 0; +} +``` + +The 2nd way is to use `vm->bind`'s last parameter `userdata`, you can store a POD type smaller than 8 bytes. +And use `lambda_get_userdata(args.begin())` to get it inside the lambda body. + +```cpp +int x = 1; +vm->bind(obj, "f() -> int", [](VM* vm, ArgsView args){ + // get the userdata + int x = lambda_get_userdata(args.begin()); + return py_var(vm, x); +}, x); // capture x +``` + +The 3rd way is to change the macro `PK_ENABLE_STD_FUNCTION` in `config.h`: +```cpp +#define PK_ENABLE_STD_FUNCTION 0 // => 1 +``` + +Then you can use standard capture list in lambda. + ### Bind a struct Assume you have a struct `Point` declared as follows. From c64e8ce7b6246dc8c5dd2e5f4ebf84ebf760a24a Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 8 Oct 2023 16:28:35 +0800 Subject: [PATCH 20/28] ... --- docs/bindings.md | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/docs/bindings.md b/docs/bindings.md index 3fd78614..d193defc 100644 --- a/docs/bindings.md +++ b/docs/bindings.md @@ -191,6 +191,41 @@ int main(){ } ``` +#### Handle gc for container types + +If your custom type stores `PyObject*` in its fields, you need to handle gc for them. + +```cpp +struct Container{ + PY_CLASS(Container, builtins, Container) + + PyObject* a; + std::vector b; + // ... +} +``` + +Add a magic method `_gc_mark() const` to your custom type. + +```cpp +struct Container{ + PY_CLASS(Container, builtins, Container) + + PyObject* a; + std::vector b; + // ... + + void _gc_mark() const{ + // mark a + if(a) PK_OBJ_MARK(a); + + // mark elements in b + for(PyObject* obj : b){ + if(obj) PK_OBJ_MARK(obj); + } + } +} +``` ### Others @@ -203,7 +238,7 @@ They do not take universal function pointer as argument. You need to provide the detailed `Type` object and the corresponding function pointer. ```cpp -PyObject* f_add(PyObject* lhs, PyObject* rhs){ +PyObject* f_add(VM* vm, PyObject* lhs, PyObject* rhs){ int a = py_cast(vm, lhs); int b = py_cast(vm, rhs); return py_var(vm, a + b); From e26ea4a95ca9dff6ea4bb77206b965b0cbed4658 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 8 Oct 2023 16:33:50 +0800 Subject: [PATCH 21/28] ... --- docs/bindings.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/bindings.md b/docs/bindings.md index d193defc..7ace3cf7 100644 --- a/docs/bindings.md +++ b/docs/bindings.md @@ -254,4 +254,4 @@ For example, `vm->bind__add__` is preferred over `vm->bind_method<1>(type, "__ad ### Further reading -See [linalg.h](https://github.com/blueloveTH/pocketpy/blob/main/src/random.cpp) for a complete example used by `random` module. \ No newline at end of file +See [random.cpp](https://github.com/blueloveTH/pocketpy/blob/main/src/random.cpp) for an example used by `random` module. \ No newline at end of file From 27e40e61bdfab692348808692c609d6e4cc54398 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 8 Oct 2023 16:44:15 +0800 Subject: [PATCH 22/28] some fix --- tests/80_linalg.py | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/tests/80_linalg.py b/tests/80_linalg.py index 0b6eae2c..77c2aee6 100644 --- a/tests/80_linalg.py +++ b/tests/80_linalg.py @@ -327,23 +327,12 @@ assert result_mat == correct_result_mat # test determinant test_mat_copy = test_mat.copy() -list_mat = [[0,0,0], [0,0,0], [0,0,0]] -for i in range(3): - for j in range(3): - list_mat[i][j] = test_mat[i, j] -determinant = list_mat[0][0]*(list_mat[1][1]*list_mat[2][2] - list_mat[1][2]*list_mat[2][1]) - list_mat[0][1]*(list_mat[1][0]*list_mat[2][2] - list_mat[1][2]*list_mat[2][0]) + list_mat[0][2]*(list_mat[1][0]*list_mat[2][1] - list_mat[1][1]*list_mat[2][0]) -_0 = determinant -_1 = test_mat_copy.determinant() -_0, _1 = round(_0, 2), round(_1, 2) -assert (_0 == _1), f'{_0} != {_1}' - - +test_mat_copy.determinant() # test __repr__ assert str(static_test_mat_float) == 'mat3x3([[7.2642, -5.4322, 1.8765],\n [-2.4911, 8.9897, -0.7169],\n [9.5580, -3.3363, 4.9514]])' assert str(static_test_mat_int) == 'mat3x3([[1.0000, 2.0000, 3.0000],\n [4.0000, 5.0000, 6.0000],\n [7.0000, 8.0000, 9.0000]])' - # test __getnewargs__ test_mat_copy = test_mat.copy() element_value_list = [getattr(test_mat, attr) for attr in element_name_list] From e26f38918234d3d9dc88cb567aae644b274d2013 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 8 Oct 2023 20:09:22 +0800 Subject: [PATCH 23/28] fix `assert` message won't be evaluated on true cond --- include/pocketpy/opcodes.h | 3 ++- src/ceval.cpp | 24 +++++++++++------------- src/compiler.cpp | 14 +++++++++++--- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/include/pocketpy/opcodes.h b/include/pocketpy/opcodes.h index 1d34506b..7ce73324 100644 --- a/include/pocketpy/opcodes.h +++ b/include/pocketpy/opcodes.h @@ -81,6 +81,7 @@ OPCODE(CONTAINS_OP) /**************************/ OPCODE(JUMP_ABSOLUTE) OPCODE(POP_JUMP_IF_FALSE) +OPCODE(POP_JUMP_IF_TRUE) OPCODE(JUMP_IF_TRUE_OR_POP) OPCODE(JUMP_IF_FALSE_OR_POP) OPCODE(SHORTCUT_IF_FALSE_OR_POP) @@ -120,9 +121,9 @@ OPCODE(STORE_CLASS_ATTR) OPCODE(WITH_ENTER) OPCODE(WITH_EXIT) /**************************/ -OPCODE(ASSERT) OPCODE(EXCEPTION_MATCH) OPCODE(RAISE) +OPCODE(RAISE_ASSERT) OPCODE(RE_RAISE) OPCODE(POP_EXCEPTION) /**************************/ diff --git a/src/ceval.cpp b/src/ceval.cpp index bd867b2b..40ec6dd2 100644 --- a/src/ceval.cpp +++ b/src/ceval.cpp @@ -473,6 +473,9 @@ __NEXT_STEP:; TARGET(POP_JUMP_IF_FALSE) if(!py_bool(POPX())) frame->jump_abs(byte.arg); DISPATCH(); + TARGET(POP_JUMP_IF_TRUE) + if(py_bool(POPX())) frame->jump_abs(byte.arg); + DISPATCH(); TARGET(JUMP_IF_TRUE_OR_POP) if(py_bool(TOP()) == true) frame->jump_abs(byte.arg); else POP(); @@ -682,19 +685,6 @@ __NEXT_STEP:; call_method(POPX(), __exit__); DISPATCH(); /*****************************************/ - TARGET(ASSERT) { - _0 = TOP(); - Str msg; - if(is_type(_0, tp_tuple)){ - auto& t = CAST(Tuple&, _0); - if(t.size() != 2) ValueError("assert tuple must have 2 elements"); - _0 = t[0]; - msg = CAST(Str&, py_str(t[1])); - } - bool ok = py_bool(_0); - POP(); - if(!ok) _error("AssertionError", msg); - } DISPATCH(); TARGET(EXCEPTION_MATCH) { const auto& e = CAST(Exception&, TOP()); _name = StrName(byte.arg); @@ -705,6 +695,14 @@ __NEXT_STEP:; Str msg = _0 == None ? "" : CAST(Str, py_str(_0)); _error(StrName(byte.arg), msg); } DISPATCH(); + TARGET(RAISE_ASSERT) + if(byte.arg){ + _0 = py_str(POPX()); + _error("AssertionError", CAST(Str, _0)); + }else{ + _error("AssertionError", ""); + } + DISPATCH(); TARGET(RE_RAISE) _raise(true); DISPATCH(); TARGET(POP_EXCEPTION) _last_exception = POPX(); DISPATCH(); /*****************************************/ diff --git a/src/compiler.cpp b/src/compiler.cpp index 86f806fd..38daac0d 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -802,11 +802,19 @@ __EAT_DOTS_END: consume_end_stmt(); break; } - case TK("assert"): - EXPR_TUPLE(false); - ctx()->emit(OP_ASSERT, BC_NOARG, kw_line); + case TK("assert"):{ + EXPR(false); // condition + int index = ctx()->emit(OP_POP_JUMP_IF_TRUE, BC_NOARG, kw_line); + int has_msg = 0; + if(match(TK(","))){ + EXPR(false); // message + has_msg = 1; + } + ctx()->emit(OP_RAISE_ASSERT, has_msg, kw_line); + ctx()->patch_jump(index); consume_end_stmt(); break; + } case TK("global"): do { consume(TK("@id")); From 0caa14172dfa805bf828867b5d4269da5eb3198e Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 8 Oct 2023 20:55:31 +0800 Subject: [PATCH 24/28] fix `++` for `global` names --- src/compiler.cpp | 5 ++++- tests/99_bugs.py | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index 38daac0d..879ca10c 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -775,7 +775,10 @@ __EAT_DOTS_END: case TK("++"):{ consume(TK("@id")); StrName name(prev().sv()); - switch(name_scope()){ + NameScope scope = name_scope(); + bool is_global = ctx()->global_names.count(name.sv()); + if(is_global) scope = NAME_GLOBAL; + switch(scope){ case NAME_LOCAL: ctx()->emit(OP_INC_FAST, ctx()->add_varname(name), prev().line); break; diff --git a/tests/99_bugs.py b/tests/99_bugs.py index c86a8813..07f7949a 100644 --- a/tests/99_bugs.py +++ b/tests/99_bugs.py @@ -70,3 +70,12 @@ try: exit(1) except UnboundLocalError: pass + + +g = 1 +def f(): + global g + ++g + +f(); f() +assert g == 3 \ No newline at end of file From 6dad2d612ef72353bc54ddd5a962de0afe9a8cdc Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Mon, 9 Oct 2023 00:03:23 +0800 Subject: [PATCH 25/28] ... --- build.sh | 2 +- docs/bindings.md | 6 ++++++ include/typings/c.pyi | 5 ++++- src/cffi.cpp | 16 ++++++++++++++++ tests/80_c.py | 14 +++++++++++++- 5 files changed, 40 insertions(+), 3 deletions(-) diff --git a/build.sh b/build.sh index 0a2303f4..12648298 100644 --- a/build.sh +++ b/build.sh @@ -14,7 +14,7 @@ if ! type -P clang++ >/dev/null 2>&1; then exit 1 fi -echo "Requirements satisfied: python3 and clang++ are installed." +echo "Requirements satisfied: python3 and clang are installed." echo "It takes a moment to finish building." echo "" echo "> Running prebuild.py... " diff --git a/docs/bindings.md b/docs/bindings.md index 7ace3cf7..98ad9742 100644 --- a/docs/bindings.md +++ b/docs/bindings.md @@ -227,6 +227,12 @@ struct Container{ } ``` +For global objects, use the callback in `vm->heap`. +```cpp +void (*_gc_marker_ex)(VM*) = nullptr; +``` +It will be invoked before a GC starts. So you can mark objects inside the callback to keep them alive. + ### Others You may see somewhere in the code that `vm->bind_method<>` or `vm->bind_func<>` is used. diff --git a/include/typings/c.pyi b/include/typings/c.pyi index 1ab69684..06b1345f 100644 --- a/include/typings/c.pyi +++ b/include/typings/c.pyi @@ -32,7 +32,10 @@ class Pointer(Generic[T], void_p): def __getitem__(self, index: int) -> T: ... def __setitem__(self, index: int, value: T) -> None: ... -class char_p(Pointer[int]): pass +class char_p(Pointer[int]): + def read_string(self) -> str: ... + def write_string(self, value: str) -> None: ... + class uchar_p(Pointer[int]): pass class short_p(Pointer[int]): pass class ushort_p(Pointer[int]): pass diff --git a/src/cffi.cpp b/src/cffi.cpp index 2d23bdb1..7bdf6023 100644 --- a/src/cffi.cpp +++ b/src/cffi.cpp @@ -226,6 +226,22 @@ void add_module_c(VM* vm){ BIND_PRIMITIVE(bool, "bool") #undef BIND_PRIMITIVE + + PyObject* char_p_t = mod->attr("char_p"); + vm->bind(char_p_t, "read_string(self) -> str", [](VM* vm, ArgsView args){ + VoidP& voidp = PK_OBJ_GET(VoidP, args[0]); + const char* target = (const char*)voidp.ptr; + return VAR(target); + }); + + vm->bind(char_p_t, "write_string(self, value: str)", [](VM* vm, ArgsView args){ + VoidP& voidp = PK_OBJ_GET(VoidP, args[0]); + std::string_view sv = CAST(Str&, args[1]).sv(); + char* target = (char*)voidp.ptr; + memcpy(target, sv.data(), sv.size()); + target[sv.size()] = '\0'; + return vm->None; + }); } } // namespace pkpy \ No newline at end of file diff --git a/tests/80_c.py b/tests/80_c.py index f61484c6..55d4d854 100644 --- a/tests/80_c.py +++ b/tests/80_c.py @@ -49,4 +49,16 @@ class Vec2(c.struct): a = Vec2(1, 2) assert isinstance(a, c.struct) assert type(a) is Vec2 -assert repr(a) == "Vec2(1.0, 2.0)" \ No newline at end of file +assert repr(a) == "Vec2(1.0, 2.0)" + +a = c.struct(10) +p = c.p_cast(a.addr(), c.char_p) +p.write_string("Hello!") +assert p[0] == ord("H") +assert p[1] == ord("e") +assert p[2] == ord("l") +assert p[3] == ord("l") +assert p[4] == ord("o") +assert p[5] == ord("!") +assert p[6] == 0 +assert p.read_string() == "Hello!" From bb0bd293a0f0f4f9df3f80f151483c8f323b307c Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Tue, 10 Oct 2023 12:04:21 +0800 Subject: [PATCH 26/28] ... --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index bb9875f6..ec1c9cf6 100644 --- a/README.md +++ b/README.md @@ -136,6 +136,17 @@ for a quick overview of the supported features. | Generator | `yield i` | ✅ | | Decorator | `@cache` | ✅ | +## Used By + +| | Description | +| ------------------------------------------------------------ | ------------------------------------------------------------ | +| [TIC-80](https://github.com/nesbox/TIC-80) | TIC-80 is a fantasy computer for making, playing and sharing tiny games. | +| [ct-py](https://github.com/blueloveTH/ct-py) | Ct.py🥕 is cross-platform 2D game framework built on raylib and imgui. | +| [MiniPythonIDE](https://github.com/CU-Production/MiniPythonIDE) | A python ide base on pocketpy | +| [py-js](https://github.com/shakfu/py-js) | Python3 externals for Max / MSP | + +Submit a pull request to add your project here. + ## Contribution All kinds of contributions are welcome. From 13ee2c3c047dd5d04867f77e45518888a87022b2 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Tue, 10 Oct 2023 18:19:32 +0800 Subject: [PATCH 27/28] ... --- README.md | 2 +- docs/coding_style_guide.md | 15 +++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ec1c9cf6..382a2691 100644 --- a/README.md +++ b/README.md @@ -158,7 +158,7 @@ All kinds of contributions are welcome. - any suggestions - any questions -Check our [Coding Style Guide](https://pocketpy.dev/coding_style_guide/) if you want to contribute C++ code. +If you find this project useful, consider star this repository (●'◡'●) ## Reference diff --git a/docs/coding_style_guide.md b/docs/coding_style_guide.md index 647ba259..bb72487f 100644 --- a/docs/coding_style_guide.md +++ b/docs/coding_style_guide.md @@ -6,7 +6,14 @@ label: Coding style guide # Coding Style Guide -## Naming rules + +## For Python + +Use [PEP-8](https://www.python.org/dev/peps/pep-0008/) as the coding style guide. + +## For C++ + +### Naming rules For class names, always use **PascalCase** @@ -53,7 +60,7 @@ For macros, use **SNAKE_CASE** #define TEST(x) x+1 ``` -## Access control +### Access control Please use python style access control. @@ -74,7 +81,7 @@ public: It does not forbid users to access internal members. -## Use compact style +### Use compact style Try to make the code compact if it does not affect readability. @@ -88,7 +95,7 @@ if(x == 1){ } ``` -## For `std::shared_ptr` +### For `std::shared_ptr` Use a `_` suffix to indicate a type is a shared pointer. From 69f9252da9d34ec4ad4b5bbc4cf1d485d4fbb5f1 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Tue, 10 Oct 2023 18:27:18 +0800 Subject: [PATCH 28/28] ... --- README.md | 6 +++++- docs/index.md | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 382a2691..005df4fd 100644 --- a/README.md +++ b/README.md @@ -158,7 +158,11 @@ All kinds of contributions are welcome. - any suggestions - any questions -If you find this project useful, consider star this repository (●'◡'●) +If you find pocketpy useful, consider star this repository (●'◡'●) + +## Sponsor me + +You can sponsor me via [Github Sponsors](https://github.com/sponsors/blueloveTH). Your sponsorship will help me develop this project continuously. ## Reference diff --git a/docs/index.md b/docs/index.md index 08ed87c3..5fbf82e0 100644 --- a/docs/index.md +++ b/docs/index.md @@ -41,6 +41,10 @@ These platforms are officially tested. + Emscripten 32-bit + Raspberry Pi OS 64-bit +## Star the repo + +If you find pocketpy useful, consider [star this repository](https://github.com/blueloveth/pocketpy) (●'◡'●) + ## Sponsor me -You can sponsor me via [Github Sponsors](https://github.com/sponsors/blueloveTH). +You can sponsor me via [Github Sponsors](https://github.com/sponsors/blueloveTH). Your sponsorship will help me develop this project continuously.