cjson cleanup

This commit is contained in:
blueloveTH 2023-10-15 15:00:25 +08:00
parent 2950d88545
commit 227e76e3e4
17 changed files with 48326 additions and 88 deletions

View File

@ -20,14 +20,9 @@ jobs:
shell: bash
run: |
mkdir -p output/windows/x86_64
mkdir build
cd build
cmake ..
cmake --build . --config Release
cp Release/main.exe ../output/windows/x86_64
cp Release/pocketpy.dll ../output/windows/x86_64
cp Release/main.exe ../
cp Release/pocketpy.dll ../
python3 cmake_build.py
cp main.exe output/windows/x86_64
cp pocketpy.dll output/windows/x86_64
- uses: actions/upload-artifact@v3
with:
path: output
@ -59,14 +54,9 @@ jobs:
export CXX=clang++
export CC=clang
mkdir -p output/linux/x86_64
mkdir build
cd build
cmake .. -DPK_USE_BOX2D=ON
cmake --build . --config Release
cp main ../output/linux/x86_64
cp libpocketpy.so ../output/linux/x86_64
cp main ../
cp libpocketpy.so ../
python3 cmake_build.py
cp main output/linux/x86_64
cp libpocketpy.so output/linux/x86_64
- uses: actions/upload-artifact@v3
with:
path: output
@ -87,13 +77,7 @@ jobs:
- name: Build and Test
run: |
uname -m
mkdir build
cd build
cmake ..
cmake --build . --config Release
cp main ../
cp libpocketpy.so ../
cd ..
python3 cmake_build.py
python3 scripts/run_tests.py
python3 scripts/run_tests.py benchmark
shell: alpine.sh {0}
@ -103,13 +87,7 @@ jobs:
- uses: actions/checkout@v3
- name: Compile and Test
run: |
mkdir build
cd build
cmake ..
cmake --build . --config Release
cp main ../
cp libpocketpy.dylib ../
cd ..
python3 cmake_build.py
python3 scripts/run_tests.py
- name: Benchmark
run: python3 scripts/run_tests.py benchmark

3
.gitignore vendored
View File

@ -36,7 +36,4 @@ pypi/
libpocketpy.dylib
.xmake/
tests/res/WorldMap_Free_layout.ldtk
tests/res/WorldMap_GridVania_layout.ldtk
*.gcda

View File

@ -14,7 +14,7 @@ aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/src/rope BOX2D_SRC_3)
aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/src BOX2D_BINDINGS_SRC)
set(CMAKE_CXX_FLAGS_RELEASE "-O2")
set(CMAKE_CXX_FLAGS "-O2")
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
add_library(

View File

@ -8,8 +8,8 @@ set(CMAKE_CXX_STANDARD 17)
include_directories(${CMAKE_CURRENT_LIST_DIR}/include)
include_directories(${CMAKE_CURRENT_LIST_DIR}/../pocketpy/include)
set(CMAKE_C_FLAGS_RELEASE "-O2")
set(CMAKE_CXX_FLAGS_RELEASE "-O2")
set(CMAKE_C_FLAGS "-O2")
set(CMAKE_CXX_FLAGS "-O2")
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
add_library(

View File

@ -34,9 +34,13 @@ include_directories(${CMAKE_CURRENT_LIST_DIR}/include)
aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/src POCKETPY_SRC)
option(PK_USE_BOX2D "Use Box2D" OFF)
option(PK_USE_CJSON "Use cJSON" ON)
option(PK_USE_CJSON "Use cJSON" OFF)
option(PK_USE_DYLIB "Use dylib" OFF)
if(PK_USE_DYLIB)
add_definitions(-DPK_USE_DYLIB)
endif()
if(PK_USE_BOX2D)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/3rd/box2d)
include_directories(${CMAKE_CURRENT_LIST_DIR}/3rd/box2d/include)
@ -61,8 +65,6 @@ else()
option(PK_BUILD_STATIC_LIB "Build static library" ON)
endif()
option(PK_EXPORT_CXX_SYMBOLS "Export C++ symbols" OFF)
if(PK_BUILD_SHARED_LIB)
add_library(${PROJECT_NAME} SHARED ${POCKETPY_SRC})
elseif(PK_BUILD_STATIC_LIB)
@ -76,7 +78,6 @@ else()
endif()
if(PK_USE_DYLIB)
add_definitions(-DPK_USE_DYLIB)
target_link_libraries(${PROJECT_NAME} ${CMAKE_DL_LIBS})
endif()
@ -84,16 +85,6 @@ if(PK_USE_BOX2D)
target_link_libraries(${PROJECT_NAME} box2d)
endif()
target_link_libraries(${PROJECT_NAME} cjson)
if(PK_EXPORT_CXX_SYMBOLS AND MSVC)
set_target_properties(${PROJECT_NAME} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON)
if(PK_USE_CJSON)
target_link_libraries(${PROJECT_NAME} cjson)
endif()
# enable link time optimization
# include(CheckIPOSupported)
# check_ipo_supported(RESULT result)
# if(result)
# message(STATUS "LTO enabled")
# set_target_properties(${PROJECT_NAME} PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
# endif()

22
benchmarks/ldtk_cjson.py Normal file
View File

@ -0,0 +1,22 @@
import sys
is_pkpy = not hasattr(sys, 'getrefcount')
if is_pkpy:
import cjson as json
else:
import json
_2489KB = 'WorldMap_GridVania_layout.ldtk'
_1093KB = 'WorldMap_Free_layout.ldtk'
_339KB = 'Typical_2D_platformer_example.ldtk'
with open(f'res/{_2489KB}', 'r') as f:
json_content = f.read()
data: dict = json.loads(json_content)
assert isinstance(data, dict)
# dumped: str = json.dumps(data)
# loaded: dict = json.loads(dumped)
# assert len(data) == len(loaded)
# assert data == loaded

View File

@ -1,22 +1,19 @@
try:
import cjson as json
print('[INFO] cjson is used')
except ImportError:
import json
import json
_2489KB = 'WorldMap_GridVania_layout.ldtk'
_1093KB = 'WorldMap_Free_layout.ldtk'
_339KB = 'Typical_2D_platformer_example.ldtk'
with open(f'res/{_339KB}', 'r') as f:
with open(f'res/{_2489KB}', 'r') as f:
json_content = f.read()
data: dict = json.loads(json_content)
assert isinstance(data, dict)
dumped: str = json.dumps(data)
loaded: dict = json.loads(dumped)
assert data == loaded
# dumped: str = json.dumps(data)
# loaded: dict = json.loads(dumped)
# assert len(data) == len(loaded)
# assert data == loaded
# import pickle
##### very very slow!! DO NOT RUN IT

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,12 +0,0 @@
if (Test-Path build) {
Remove-Item -Recurse -Force build
}
New-Item -ItemType Directory -Path build
Push-Location build
cmake ..
cmake --build . --config Release
Copy-Item "Release\main.exe" -Destination ".." # Note: NTFS uses backslash (\) instead of slashes (*nix, /)
Copy-Item "Release\pocketpy.dll" -Destination ".."

23
cmake_build.py Normal file
View File

@ -0,0 +1,23 @@
import os
import sys
import shutil
if not os.path.exists("build"):
os.mkdir("build")
os.chdir("build")
os.system(r"""
cmake .. -DPK_USE_CJSON=ON -DPK_USE_BOX2D=ON
cmake --build . --config Release
""")
if sys.platform == "win32":
shutil.copy("Release/main.exe", "../main.exe")
shutil.copy("Release/pocketpy.dll", "../pocketpy.dll")
elif sys.platform == "darwin":
shutil.copy("main", "../main")
shutil.copy("libpocketpy.dylib", "../libpocketpy.dylib")
else:
shutil.copy("main", "../main")
shutil.copy("libpocketpy.so", "../libpocketpy.so")

View File

@ -144,6 +144,8 @@ struct PyObject{
NameDict& attr() noexcept { return *_attr; }
PyObject* attr(StrName name) const noexcept { return (*_attr)[name]; }
// PyObject* operator[](StrName name) const noexcept { return (*_attr)[name]; }
virtual void _obj_gc_mark() = 0;
virtual void* _value_ptr() = 0;

View File

@ -2,9 +2,22 @@ import os
import sys
import time
class WorkDir:
def __init__(self, next):
self.prev = os.getcwd()
self.next = next
def __enter__(self):
os.chdir(self.next)
def __exit__(self, *args, **kwargs):
os.chdir(self.prev)
def test_file(filepath, cpython=False):
if cpython:
return os.system("python3 " + filepath) == 0
x, y = os.path.split(filepath)
with WorkDir(x):
return os.system("python3 " + y) == 0
if sys.platform == 'win32':
return os.system("main.exe " + filepath) == 0
else:

View File

@ -32,24 +32,27 @@ namespace pkpy{
// however, this is buggy...since there may be a jump to the end (out of bound) even if the last opcode is a return
ctx()->emit(OP_LOAD_NONE, BC_NOARG, BC_KEEPLINE);
ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
// ctx()->co->optimize(vm);
// some check here
std::vector<Bytecode>& codes = ctx()->co->codes;
if(ctx()->co->varnames.size() > PK_MAX_CO_VARNAMES){
SyntaxError("maximum number of local variables exceeded");
}
FuncDecl_ func = contexts.top().func;
if(func){
func->is_simple = true;
if(func->code->is_generator) func->is_simple = false;
if(func->kwargs.size() > 0) func->is_simple = false;
if(func->starred_arg >= 0) func->is_simple = false;
if(func->starred_kwarg >= 0) func->is_simple = false;
if(ctx()->co->consts.size() > 65535){
// std::map<std::string, int> counts;
// for(PyObject* c: ctx()->co->consts){
// std::string key = obj_type_name(vm, vm->_tp(c)).str();
// counts[key] += 1;
// }
// for(auto pair: counts){
// std::cout << pair.first << ": " << pair.second << std::endl;
// }
SyntaxError("maximum number of constants exceeded");
}
// pre-compute LOOP_BREAK and LOOP_CONTINUE and FOR_ITER
std::vector<Bytecode>& codes = ctx()->co->codes;
if(codes.size() > 65535 && ctx()->co->src->mode != JSON_MODE){
// json mode does not contain jump instructions, so it is safe to ignore this check
SyntaxError("maximum number of opcodes exceeded, please split your code into smaller functions");
SyntaxError("maximum number of opcodes exceeded");
}
// pre-compute LOOP_BREAK and LOOP_CONTINUE and FOR_ITER
for(int i=0; i<codes.size(); i++){
Bytecode& bc = codes[i];
if(bc.op == OP_LOOP_CONTINUE){
@ -60,6 +63,14 @@ namespace pkpy{
bc.arg = ctx()->co->_get_block_codei(i).end;
}
}
FuncDecl_ func = contexts.top().func;
if(func){
func->is_simple = true;
if(func->code->is_generator) func->is_simple = false;
if(func->kwargs.size() > 0) func->is_simple = false;
if(func->starred_arg >= 0) func->is_simple = false;
if(func->starred_kwarg >= 0) func->is_simple = false;
}
contexts.pop();
}

View File

@ -1,5 +1,4 @@
#include "pocketpy/expr.h"
#include "pocketpy/codeobject.h"
namespace pkpy{
@ -88,6 +87,15 @@ namespace pkpy{
for(int i=0; i<co->consts.size(); i++){
if(co->consts[i] == v) return i;
}
// string deduplication
if(is_non_tagged_type(v, vm->tp_str)){
const Str& v_str = PK_OBJ_GET(Str, v);
for(int i=0; i<co->consts.size(); i++){
if(is_non_tagged_type(co->consts[i], vm->tp_str)){
if(PK_OBJ_GET(Str, co->consts[i]) == v_str) return i;
}
}
}
co->consts.push_back(v);
return co->consts.size() - 1;
}

View File

@ -139,7 +139,7 @@ void init_builtins(VM* _vm) {
vm->check_non_tagged_type(class_arg, vm->tp_type);
Type type = PK_OBJ_GET(Type, class_arg);
if(!vm->isinstance(self_arg, type)){
Str _0 = obj_type_name(vm, PK_OBJ_GET(Type, vm->_t(self_arg)));
Str _0 = obj_type_name(vm, vm->_tp(self_arg));
Str _1 = obj_type_name(vm, type);
vm->TypeError("super(): " + _0.escape() + " is not an instance of " + _1.escape());
}
@ -1331,7 +1331,11 @@ void init_builtins(VM* _vm) {
self.apply([&](PyObject* k, PyObject* v){
if(!first) ss << ", ";
first = false;
Str key = CAST(Str&, k).escape(false);
if(!is_non_tagged_type(k, vm->tp_str)){
vm->TypeError(fmt("json keys must be string, got ", obj_type_name(vm, vm->_tp(k))));
UNREACHABLE();
}
Str key = _CAST(Str&, k).escape(false);
Str value = CAST(Str&, vm->py_json(v));
ss << key << ": " << value;
});