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 diff --git a/README.md b/README.md index f0063c8d..bb9875f6 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 @@ -56,11 +56,12 @@ 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 # 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 @@ -114,26 +115,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 diff --git a/README_zh.md b/README_zh.md index 9e1394b8..007ab2f4 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 ## 快速上手 @@ -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` | ✅ | ## 参考 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 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 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 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. diff --git a/python/builtins.py b/python/builtins.py index 4abb8187..436cd39c 100644 --- a/python/builtins.py +++ b/python/builtins.py @@ -96,14 +96,115 @@ def sorted(iterable, reverse=False, key=None): return a ##### str ##### -def __f(self, *args): - 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])) - return self +def __f(self: str, *args, **kwargs) -> str: + def tokenizeString(s: str): + tokens = [] + L, R = 0,0 + + mode = None + curArg = 0 + # lookingForKword = False + + while(R_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/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" 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) 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