mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
Merge branch 'main' of https://github.com/blueloveTH/pocketpy
This commit is contained in:
commit
3e65101a0d
35
.github/workflows/website.yml
vendored
Normal file
35
.github/workflows/website.yml
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
name: website
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
###################################################
|
||||||
|
- uses: actions/setup-node@v3.1.1
|
||||||
|
- name: Retype build
|
||||||
|
run: |
|
||||||
|
cd docs
|
||||||
|
npm install retypeapp --global
|
||||||
|
retype build
|
||||||
|
###################################################
|
||||||
|
- name: Setup emsdk
|
||||||
|
uses: mymindstorm/setup-emsdk@v12
|
||||||
|
with:
|
||||||
|
version: 3.1.25
|
||||||
|
actions-cache-folder: 'emsdk-cache'
|
||||||
|
- name: Compile
|
||||||
|
run: |
|
||||||
|
bash build_web.sh
|
||||||
|
mv web docs/.retype/static
|
||||||
|
###################################################
|
||||||
|
- uses: crazy-max/ghaction-github-pages@v3
|
||||||
|
with:
|
||||||
|
target_branch: gh-pages
|
||||||
|
build_dir: docs/.retype
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
@ -20,12 +20,14 @@ endif()
|
|||||||
if(MSVC)
|
if(MSVC)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR- /EHsc /utf-8 /O2")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR- /EHsc /utf-8 /O2")
|
||||||
else()
|
else()
|
||||||
|
if (NOT EMSCRIPTEN)
|
||||||
find_program(CLANGPP clang++)
|
find_program(CLANGPP clang++)
|
||||||
if(CLANGPP)
|
if(CLANGPP)
|
||||||
message(STATUS "Using clang with libc++")
|
message(STATUS "Using clang with libc++")
|
||||||
set(CMAKE_CXX_COMPILER ${CLANGPP})
|
set(CMAKE_CXX_COMPILER ${CLANGPP})
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||||
endif()
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fexceptions -O2")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fexceptions -O2")
|
||||||
endif()
|
endif()
|
||||||
|
7
build_web.sh
Normal file
7
build_web.sh
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
python3 prebuild.py
|
||||||
|
|
||||||
|
rm -rf web/lib
|
||||||
|
mkdir web/lib
|
||||||
|
|
||||||
|
SRC=$(find src/ -name "*.cpp")
|
||||||
|
em++ $SRC -Iinclude/ -fno-rtti -fexceptions -O3 -sEXPORTED_FUNCTIONS=_pkpy_new_repl,_pkpy_repl_input,_pkpy_new_vm -sEXPORTED_RUNTIME_METHODS=ccall -o web/lib/pocketpy.js
|
@ -20,7 +20,7 @@
|
|||||||
#include <variant>
|
#include <variant>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
#define PK_VERSION "1.0.8"
|
#define PK_VERSION "1.0.9"
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
@ -22,10 +22,7 @@ struct FastLocals{
|
|||||||
FastLocals(const CodeObject* co, PyObject** a): varnames_inv(&co->varnames_inv), a(a) {}
|
FastLocals(const CodeObject* co, PyObject** a): varnames_inv(&co->varnames_inv), a(a) {}
|
||||||
FastLocals(const FastLocals& other): varnames_inv(other.varnames_inv), a(other.a) {}
|
FastLocals(const FastLocals& other): varnames_inv(other.varnames_inv), a(other.a) {}
|
||||||
|
|
||||||
PyObject* try_get(StrName name);
|
PyObject** try_get_name(StrName name);
|
||||||
bool contains(StrName name);
|
|
||||||
void erase(StrName name);
|
|
||||||
bool try_set(StrName name, PyObject* value);
|
|
||||||
NameDict_ to_namedict();
|
NameDict_ to_namedict();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -351,6 +351,7 @@ public:
|
|||||||
void IndexError(const Str& msg){ _error("IndexError", msg); }
|
void IndexError(const Str& msg){ _error("IndexError", msg); }
|
||||||
void ValueError(const Str& msg){ _error("ValueError", msg); }
|
void ValueError(const Str& msg){ _error("ValueError", msg); }
|
||||||
void NameError(StrName name){ _error("NameError", fmt("name ", name.escape() + " is not defined")); }
|
void NameError(StrName name){ _error("NameError", fmt("name ", name.escape() + " is not defined")); }
|
||||||
|
void UnboundLocalError(StrName name){ _error("UnboundLocalError", fmt("local variable ", name.escape() + " referenced before assignment")); }
|
||||||
void KeyError(PyObject* obj){ _error("KeyError", PK_OBJ_GET(Str, py_repr(obj))); }
|
void KeyError(PyObject* obj){ _error("KeyError", PK_OBJ_GET(Str, py_repr(obj))); }
|
||||||
void BinaryOptError(const char* op) { TypeError(fmt("unsupported operand type(s) for ", op)); }
|
void BinaryOptError(const char* op) { TypeError(fmt("unsupported operand type(s) for ", op)); }
|
||||||
|
|
||||||
|
@ -111,11 +111,15 @@ __NEXT_STEP:;
|
|||||||
if(_0 == PY_NULL) vm->NameError(co->varnames[byte.arg]);
|
if(_0 == PY_NULL) vm->NameError(co->varnames[byte.arg]);
|
||||||
PUSH(_0);
|
PUSH(_0);
|
||||||
} DISPATCH();
|
} DISPATCH();
|
||||||
TARGET(LOAD_NAME)
|
TARGET(LOAD_NAME) {
|
||||||
heap._auto_collect();
|
heap._auto_collect();
|
||||||
_name = StrName(byte.arg);
|
_name = StrName(byte.arg);
|
||||||
_0 = frame->_locals.try_get(_name);
|
PyObject** slot = frame->_locals.try_get_name(_name);
|
||||||
if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
|
if(slot != nullptr) {
|
||||||
|
if(*slot == PY_NULL) vm->UnboundLocalError(_name);
|
||||||
|
PUSH(*slot);
|
||||||
|
DISPATCH();
|
||||||
|
}
|
||||||
_0 = frame->f_closure_try_get(_name);
|
_0 = frame->f_closure_try_get(_name);
|
||||||
if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
|
if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
|
||||||
_0 = frame->f_globals().try_get(_name);
|
_0 = frame->f_globals().try_get(_name);
|
||||||
@ -123,7 +127,7 @@ __NEXT_STEP:;
|
|||||||
_0 = vm->builtins->attr().try_get(_name);
|
_0 = vm->builtins->attr().try_get(_name);
|
||||||
if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
|
if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
|
||||||
vm->NameError(_name);
|
vm->NameError(_name);
|
||||||
DISPATCH();
|
} DISPATCH();
|
||||||
TARGET(LOAD_NONLOCAL) {
|
TARGET(LOAD_NONLOCAL) {
|
||||||
heap._auto_collect();
|
heap._auto_collect();
|
||||||
_name = StrName(byte.arg);
|
_name = StrName(byte.arg);
|
||||||
@ -164,16 +168,17 @@ __NEXT_STEP:;
|
|||||||
TARGET(STORE_FAST)
|
TARGET(STORE_FAST)
|
||||||
frame->_locals[byte.arg] = POPX();
|
frame->_locals[byte.arg] = POPX();
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
TARGET(STORE_NAME)
|
TARGET(STORE_NAME){
|
||||||
_name = StrName(byte.arg);
|
_name = StrName(byte.arg);
|
||||||
_0 = POPX();
|
_0 = POPX();
|
||||||
if(frame->_callable != nullptr){
|
if(frame->_callable != nullptr){
|
||||||
bool ok = frame->_locals.try_set(_name, _0);
|
PyObject** slot = frame->_locals.try_get_name(_name);
|
||||||
if(!ok) vm->NameError(_name);
|
if(slot == nullptr) vm->UnboundLocalError(_name);
|
||||||
|
*slot = _0;
|
||||||
}else{
|
}else{
|
||||||
frame->f_globals().set(_name, _0);
|
frame->f_globals().set(_name, _0);
|
||||||
}
|
}
|
||||||
DISPATCH();
|
} DISPATCH();
|
||||||
TARGET(STORE_GLOBAL)
|
TARGET(STORE_GLOBAL)
|
||||||
frame->f_globals().set(StrName(byte.arg), POPX());
|
frame->f_globals().set(StrName(byte.arg), POPX());
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
@ -202,8 +207,9 @@ __NEXT_STEP:;
|
|||||||
TARGET(DELETE_NAME)
|
TARGET(DELETE_NAME)
|
||||||
_name = StrName(byte.arg);
|
_name = StrName(byte.arg);
|
||||||
if(frame->_callable != nullptr){
|
if(frame->_callable != nullptr){
|
||||||
if(!frame->_locals.contains(_name)) vm->NameError(_name);
|
PyObject** slot = frame->_locals.try_get_name(_name);
|
||||||
frame->_locals.erase(_name);
|
if(slot == nullptr) vm->UnboundLocalError(_name);
|
||||||
|
*slot = PY_NULL;
|
||||||
}else{
|
}else{
|
||||||
if(!frame->f_globals().contains(_name)) vm->NameError(_name);
|
if(!frame->f_globals().contains(_name)) vm->NameError(_name);
|
||||||
frame->f_globals().erase(_name);
|
frame->f_globals().erase(_name);
|
||||||
|
@ -1,28 +1,10 @@
|
|||||||
#include "pocketpy/frame.h"
|
#include "pocketpy/frame.h"
|
||||||
|
|
||||||
namespace pkpy{
|
namespace pkpy{
|
||||||
|
PyObject** FastLocals::try_get_name(StrName name){
|
||||||
PyObject* FastLocals::try_get(StrName name){
|
|
||||||
int index = varnames_inv->try_get(name);
|
int index = varnames_inv->try_get(name);
|
||||||
if(index == -1) return nullptr;
|
if(index == -1) return nullptr;
|
||||||
return a[index];
|
return &a[index];
|
||||||
}
|
|
||||||
|
|
||||||
bool FastLocals::contains(StrName name){
|
|
||||||
return varnames_inv->contains(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FastLocals::erase(StrName name){
|
|
||||||
int index = varnames_inv->try_get(name);
|
|
||||||
if(index == -1) FATAL_ERROR();
|
|
||||||
a[index] = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FastLocals::try_set(StrName name, PyObject* value){
|
|
||||||
int index = varnames_inv->try_get(name);
|
|
||||||
if(index == -1) return false;
|
|
||||||
a[index] = value;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NameDict_ FastLocals::to_namedict(){
|
NameDict_ FastLocals::to_namedict(){
|
||||||
|
@ -398,7 +398,11 @@ PyObject* VM::format(Str spec, PyObject* obj){
|
|||||||
int width, precision;
|
int width, precision;
|
||||||
try{
|
try{
|
||||||
if(dot >= 0){
|
if(dot >= 0){
|
||||||
|
if(dot == 0){
|
||||||
|
width = -1;
|
||||||
|
}else{
|
||||||
width = Number::stoi(spec.substr(0, dot).str());
|
width = Number::stoi(spec.substr(0, dot).str());
|
||||||
|
}
|
||||||
precision = Number::stoi(spec.substr(dot+1).str());
|
precision = Number::stoi(spec.substr(dot+1).str());
|
||||||
}else{
|
}else{
|
||||||
width = Number::stoi(spec.str());
|
width = Number::stoi(spec.str());
|
||||||
@ -424,7 +428,7 @@ PyObject* VM::format(Str spec, PyObject* obj){
|
|||||||
}else{
|
}else{
|
||||||
ret = CAST(Str&, py_str(obj));
|
ret = CAST(Str&, py_str(obj));
|
||||||
}
|
}
|
||||||
if(width > ret.length()){
|
if(width != -1 && width > ret.length()){
|
||||||
int pad = width - ret.length();
|
int pad = width - ret.length();
|
||||||
std::string padding(pad, pad_c);
|
std::string padding(pad, pad_c);
|
||||||
if(align == '>') ret = padding.c_str() + ret;
|
if(align == '>') ret = padding.c_str() + ret;
|
||||||
@ -446,7 +450,7 @@ PyObject* VM::new_module(StrName name) {
|
|||||||
static std::string _opcode_argstr(VM* vm, Bytecode byte, const CodeObject* co){
|
static std::string _opcode_argstr(VM* vm, Bytecode byte, const CodeObject* co){
|
||||||
std::string argStr = byte.arg == -1 ? "" : std::to_string(byte.arg);
|
std::string argStr = byte.arg == -1 ? "" : std::to_string(byte.arg);
|
||||||
switch(byte.op){
|
switch(byte.op){
|
||||||
case OP_LOAD_CONST:
|
case OP_LOAD_CONST: case OP_FORMAT_STRING:
|
||||||
if(vm != nullptr){
|
if(vm != nullptr){
|
||||||
argStr += fmt(" (", CAST(Str, vm->py_repr(co->consts[byte.arg])), ")");
|
argStr += fmt(" (", CAST(Str, vm->py_repr(co->consts[byte.arg])), ")");
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,8 @@ assert f'{a:010}' == '0000000010'
|
|||||||
assert f'{a:010d}' == '0000000010'
|
assert f'{a:010d}' == '0000000010'
|
||||||
assert f'{a:010f}' == '010.000000'
|
assert f'{a:010f}' == '010.000000'
|
||||||
assert f'{a:010.2f}' == '0000010.00'
|
assert f'{a:010.2f}' == '0000010.00'
|
||||||
|
assert f'{a:.2f}' == '10.00'
|
||||||
|
assert f'{a:.5f}' == '10.00000'
|
||||||
|
|
||||||
b = '123'
|
b = '123'
|
||||||
assert f'{b:10}' == '123 '
|
assert f'{b:10}' == '123 '
|
||||||
|
@ -57,3 +57,18 @@ f()
|
|||||||
|
|
||||||
# class A: a=b=1
|
# class A: a=b=1
|
||||||
# class A: a, b = 1, 2
|
# class A: a, b = 1, 2
|
||||||
|
|
||||||
|
bmi = 0.0
|
||||||
|
|
||||||
|
def test(a):
|
||||||
|
if a:
|
||||||
|
bmi = 1.4
|
||||||
|
return f'{bmi:.2f}'
|
||||||
|
|
||||||
|
assert test(1) == '1.40'
|
||||||
|
|
||||||
|
try:
|
||||||
|
assert test(0) == '0.00'
|
||||||
|
exit(1)
|
||||||
|
except UnboundLocalError:
|
||||||
|
pass
|
Loading…
x
Reference in New Issue
Block a user