mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
up
Update build.py up up
This commit is contained in:
parent
2f0aa7c89c
commit
3b13b1a988
11
.github/workflows/main.yml
vendored
11
.github/workflows/main.yml
vendored
@ -13,9 +13,8 @@ jobs:
|
|||||||
- name: Compiling
|
- name: Compiling
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
clang-cl.exe -std:c++17 -GR- -EHsc -O2 -Wno-deprecated-declarations -Fe:pocketpy src/main.cpp
|
python3 build.py windows
|
||||||
echo '#include "pocketpy.h"' > src/tmp.cpp
|
python3 build.py windows -lib
|
||||||
clang-cl.exe -std:c++17 -GR- -EHsc -O2 -Wno-deprecated-declarations -LD -Fe:pocketpy src/tmp.cpp
|
|
||||||
python3 scripts/run_tests.py
|
python3 scripts/run_tests.py
|
||||||
python3 scripts/run_tests.py benchmark
|
python3 scripts/run_tests.py benchmark
|
||||||
mkdir -p output/windows/x86_64
|
mkdir -p output/windows/x86_64
|
||||||
@ -38,7 +37,7 @@ jobs:
|
|||||||
- name: Compiling
|
- name: Compiling
|
||||||
run: |
|
run: |
|
||||||
mkdir -p output/web/lib
|
mkdir -p output/web/lib
|
||||||
bash build_wasm.sh
|
python3 build.py web
|
||||||
cp web/lib/* output/web/lib
|
cp web/lib/* output/web/lib
|
||||||
- uses: crazy-max/ghaction-github-pages@v3
|
- uses: crazy-max/ghaction-github-pages@v3
|
||||||
with:
|
with:
|
||||||
@ -62,8 +61,8 @@ jobs:
|
|||||||
- name: Compiling
|
- name: Compiling
|
||||||
run: |
|
run: |
|
||||||
sudo apt install -y libc++-15-dev libc++1-15 libc++abi-15-dev libc++abi1-15
|
sudo apt install -y libc++-15-dev libc++1-15 libc++abi-15-dev libc++abi1-15
|
||||||
bash build_cpp.sh
|
python3 build.py linux
|
||||||
bash build_linux.sh
|
python3 build.py linux -lib
|
||||||
python3 scripts/run_tests.py
|
python3 scripts/run_tests.py
|
||||||
python3 scripts/run_tests.py benchmark
|
python3 scripts/run_tests.py benchmark
|
||||||
mkdir -p output/linux/x86_64
|
mkdir -p output/linux/x86_64
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -20,3 +20,5 @@ plugins/flutter/src/pocketpy.h
|
|||||||
plugins/macos/pocketpy/pocketpy.h
|
plugins/macos/pocketpy/pocketpy.h
|
||||||
plugins/godot/godot-cpp/
|
plugins/godot/godot-cpp/
|
||||||
123.txt
|
123.txt
|
||||||
|
src/_generated.h
|
||||||
|
profile.sh
|
@ -1,11 +1,15 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
os.system("python3 preprocess.py")
|
||||||
|
|
||||||
with open("src/opcodes.h", "rt", encoding='utf-8') as f:
|
with open("src/opcodes.h", "rt", encoding='utf-8') as f:
|
||||||
OPCODES_TEXT = f.read()
|
OPCODES_TEXT = f.read()
|
||||||
|
|
||||||
pipeline = [
|
pipeline = [
|
||||||
["common.h", "memory.h", "str.h", "tuplelist.h", "namedict.h", "builtins.h", "error.h"],
|
["common.h", "memory.h", "str.h", "tuplelist.h", "namedict.h", "error.h"],
|
||||||
["obj.h", "parser.h", "codeobject.h", "frame.h"],
|
["obj.h", "parser.h", "codeobject.h", "frame.h"],
|
||||||
["vm.h", "ref.h", "ceval.h", "compiler.h", "repl.h"],
|
["vm.h", "ref.h", "ceval.h", "compiler.h", "repl.h"],
|
||||||
["iter.h", "cffi.h", "pocketpy.h"]
|
["iter.h", "cffi.h", "_generated.h", "pocketpy.h"]
|
||||||
]
|
]
|
||||||
|
|
||||||
copied = set()
|
copied = set()
|
||||||
|
50
build.py
Normal file
50
build.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
assert __name__ == "__main__"
|
||||||
|
|
||||||
|
os.system("python3 preprocess.py")
|
||||||
|
|
||||||
|
def DONE(code=0):
|
||||||
|
exit(code)
|
||||||
|
|
||||||
|
linux_common = "-Wfatal-errors --std=c++17 -O2 -Wall -Wno-sign-compare -Wno-unused-variable -fno-rtti -stdlib=libc++"
|
||||||
|
linux_cmd = "clang++ -o pocketpy src/main.cpp " + linux_common
|
||||||
|
linux_lib_cmd = "clang++ -fPIC -shared -o pocketpy.so src/tmp.cpp " + linux_common
|
||||||
|
|
||||||
|
lib_pre_cmd = r'''echo "#include \"pocketpy.h\"" > src/tmp.cpp'''
|
||||||
|
lib_post_cmd = r'''rm src/tmp.cpp'''
|
||||||
|
|
||||||
|
windows_common = "clang-cl.exe -std:c++17 -GR- -EHsc -O2 -Wno-deprecated-declarations"
|
||||||
|
windows_cmd = windows_common + " -Fe:pocketpy src/main.cpp"
|
||||||
|
windows_lib_cmd = windows_common + " -LD -Fe:pocketpy src/tmp.cpp"
|
||||||
|
|
||||||
|
if sys.argv.__len__() == 1:
|
||||||
|
os.system(linux_cmd)
|
||||||
|
DONE()
|
||||||
|
|
||||||
|
if "windows" in sys.argv:
|
||||||
|
if "-lib" in sys.argv:
|
||||||
|
os.system(lib_pre_cmd)
|
||||||
|
os.system(windows_lib_cmd)
|
||||||
|
os.system(lib_post_cmd)
|
||||||
|
else:
|
||||||
|
os.system(windows_cmd)
|
||||||
|
DONE()
|
||||||
|
|
||||||
|
if "linux" in sys.argv:
|
||||||
|
if "-lib" in sys.argv:
|
||||||
|
os.system(lib_pre_cmd)
|
||||||
|
os.system(linux_lib_cmd)
|
||||||
|
os.system(lib_post_cmd)
|
||||||
|
else:
|
||||||
|
os.system(linux_cmd)
|
||||||
|
DONE()
|
||||||
|
|
||||||
|
if "web" in sys.argv:
|
||||||
|
os.system(r'''
|
||||||
|
rm -rf web/lib/
|
||||||
|
mkdir -p web/lib/
|
||||||
|
em++ src/main.cpp -fno-rtti -fexceptions -O3 -sEXPORTED_FUNCTIONS=_pkpy_delete,_pkpy_setup_callbacks,_pkpy_new_repl,_pkpy_repl_input,_pkpy_new_vm,_pkpy_vm_add_module,_pkpy_vm_bind,_pkpy_vm_eval,_pkpy_vm_exec,_pkpy_vm_get_global,_pkpy_vm_read_output -sEXPORTED_RUNTIME_METHODS=ccall -o web/lib/pocketpy.js
|
||||||
|
''')
|
||||||
|
DONE()
|
@ -1 +0,0 @@
|
|||||||
clang++ -o pocketpy src/main.cpp -Wfatal-errors --std=c++17 -O2 -Wall -Wno-sign-compare -Wno-unused-variable -fno-rtti -stdlib=libc++ -v
|
|
@ -1,3 +0,0 @@
|
|||||||
echo '#include "pocketpy.h"' > src/tmp.cpp
|
|
||||||
clang++ -fPIC -shared -o pocketpy.so src/tmp.cpp --std=c++17 -O2 -Wall -Wno-sign-compare -Wno-unused-variable -fno-rtti -stdlib=libc++
|
|
||||||
rm src/tmp.cpp
|
|
@ -1,3 +0,0 @@
|
|||||||
rm -rf web/lib/
|
|
||||||
mkdir -p web/lib/
|
|
||||||
em++ src/main.cpp -fno-rtti -fexceptions -O3 -sEXPORTED_FUNCTIONS=_pkpy_delete,_pkpy_setup_callbacks,_pkpy_new_repl,_pkpy_repl_input,_pkpy_new_vm,_pkpy_vm_add_module,_pkpy_vm_bind,_pkpy_vm_eval,_pkpy_vm_exec,_pkpy_vm_get_global,_pkpy_vm_read_output -sEXPORTED_RUNTIME_METHODS=ccall -o web/lib/pocketpy.js
|
|
@ -2,3 +2,4 @@
|
|||||||
-Wall
|
-Wall
|
||||||
-W*
|
-W*
|
||||||
-std=c++17
|
-std=c++17
|
||||||
|
-stdlib=libc++
|
36
preprocess.py
Normal file
36
preprocess.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import os
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
def generate_python_sources():
|
||||||
|
sources = {}
|
||||||
|
for file in os.listdir("python"):
|
||||||
|
assert file.endswith(".py")
|
||||||
|
key = file.split(".")[0]
|
||||||
|
with open("python/" + file) as f:
|
||||||
|
value = f.read()
|
||||||
|
value = value.encode('utf-8').hex(':')
|
||||||
|
value = '\\x' + value.replace(':', '\\x')
|
||||||
|
sources[key] = value
|
||||||
|
|
||||||
|
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
|
header = '''#pragma once
|
||||||
|
// generated on ''' + timestamp + '''
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace pkpy{
|
||||||
|
std::map<std::string, std::string> kPythonLibs = {
|
||||||
|
'''
|
||||||
|
for key, value in sources.items():
|
||||||
|
header += ' '*8 + '{"' + key + '", "' + value + '"},'
|
||||||
|
header += '\n'
|
||||||
|
|
||||||
|
header += '''
|
||||||
|
};
|
||||||
|
} // namespace pkpy
|
||||||
|
'''
|
||||||
|
return header
|
||||||
|
|
||||||
|
with open("src/_generated.h", "w", encoding='utf-8') as f:
|
||||||
|
f.write(generate_python_sources())
|
@ -1,7 +0,0 @@
|
|||||||
g++ -o pocketpy src/main.cpp --std=c++17 -pg -O2 -fno-rtti
|
|
||||||
|
|
||||||
./pocketpy benchmarks/primes.py
|
|
||||||
|
|
||||||
gprof pocketpy gmon.out > gprof.txt
|
|
||||||
|
|
||||||
rm gmon.out
|
|
190
python/builtins.py
Normal file
190
python/builtins.py
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
def print(*args, sep=' ', end='\n'):
|
||||||
|
s = sep.join([str(i) for i in args])
|
||||||
|
__sys_stdout_write(s + end)
|
||||||
|
|
||||||
|
def round(x, ndigits=0):
|
||||||
|
assert ndigits >= 0
|
||||||
|
if ndigits == 0:
|
||||||
|
return x >= 0 ? int(x + 0.5) : int(x - 0.5)
|
||||||
|
if x >= 0:
|
||||||
|
return int(x * 10**ndigits + 0.5) / 10**ndigits
|
||||||
|
else:
|
||||||
|
return int(x * 10**ndigits - 0.5) / 10**ndigits
|
||||||
|
|
||||||
|
def isinstance(obj, cls):
|
||||||
|
assert type(cls) is type
|
||||||
|
obj_t = type(obj)
|
||||||
|
while obj_t is not None:
|
||||||
|
if obj_t is cls:
|
||||||
|
return True
|
||||||
|
obj_t = obj_t.__base__
|
||||||
|
return False
|
||||||
|
|
||||||
|
def abs(x):
|
||||||
|
return x < 0 ? -x : x
|
||||||
|
|
||||||
|
def max(a, b):
|
||||||
|
return a > b ? a : b
|
||||||
|
|
||||||
|
def min(a, b):
|
||||||
|
return a < b ? a : b
|
||||||
|
|
||||||
|
def all(iterable):
|
||||||
|
for i in iterable:
|
||||||
|
if not i:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def any(iterable):
|
||||||
|
for i in iterable:
|
||||||
|
if i:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def enumerate(iterable, start=0):
|
||||||
|
n = start
|
||||||
|
for elem in iterable:
|
||||||
|
yield n, elem
|
||||||
|
n += 1
|
||||||
|
|
||||||
|
def sum(iterable):
|
||||||
|
res = 0
|
||||||
|
for i in iterable:
|
||||||
|
res += i
|
||||||
|
return res
|
||||||
|
|
||||||
|
def map(f, iterable):
|
||||||
|
for i in iterable:
|
||||||
|
yield f(i)
|
||||||
|
|
||||||
|
def zip(a, b):
|
||||||
|
for i in range(min(len(a), len(b))):
|
||||||
|
yield (a[i], b[i])
|
||||||
|
|
||||||
|
def reversed(iterable):
|
||||||
|
a = list(iterable)
|
||||||
|
a.reverse()
|
||||||
|
return a
|
||||||
|
|
||||||
|
def sorted(iterable, reverse=False):
|
||||||
|
a = list(iterable)
|
||||||
|
a.sort(reverse=reverse)
|
||||||
|
return a
|
||||||
|
|
||||||
|
##### str #####
|
||||||
|
|
||||||
|
str.__mul__ = lambda self, n: ''.join([self for _ in range(n)])
|
||||||
|
|
||||||
|
def str::split(self, sep):
|
||||||
|
if sep == "":
|
||||||
|
return list(self)
|
||||||
|
res = []
|
||||||
|
i = 0
|
||||||
|
while i < len(self):
|
||||||
|
if self[i:i+len(sep)] == sep:
|
||||||
|
res.append(self[:i])
|
||||||
|
self = self[i+len(sep):]
|
||||||
|
i = 0
|
||||||
|
else:
|
||||||
|
i += 1
|
||||||
|
res.append(self)
|
||||||
|
return res
|
||||||
|
|
||||||
|
def str::index(self, sub):
|
||||||
|
for i in range(len(self)):
|
||||||
|
if self[i:i+len(sub)] == sub:
|
||||||
|
return i
|
||||||
|
return -1
|
||||||
|
|
||||||
|
def str::strip(self, chars=None):
|
||||||
|
chars = chars or ' \t\n\r'
|
||||||
|
i = 0
|
||||||
|
while i < len(self) and self[i] in chars:
|
||||||
|
i += 1
|
||||||
|
j = len(self) - 1
|
||||||
|
while j >= 0 and self[j] in chars:
|
||||||
|
j -= 1
|
||||||
|
return self[i:j+1]
|
||||||
|
|
||||||
|
##### list #####
|
||||||
|
|
||||||
|
list.__new__ = lambda obj: [i for i in obj]
|
||||||
|
list.__repr__ = lambda self: '[' + ', '.join([repr(i) for i in self]) + ']'
|
||||||
|
tuple.__repr__ = lambda self: '(' + ', '.join([repr(i) for i in self]) + ')'
|
||||||
|
list.__json__ = lambda self: '[' + ', '.join([i.__json__() for i in self]) + ']'
|
||||||
|
tuple.__json__ = lambda self: '[' + ', '.join([i.__json__() for i in self]) + ']'
|
||||||
|
|
||||||
|
def __qsort(a: list, L: int, R: int):
|
||||||
|
if L >= R: return;
|
||||||
|
mid = a[(R+L)//2];
|
||||||
|
i, j = L, R
|
||||||
|
while i<=j:
|
||||||
|
while a[i]<mid: i+=1
|
||||||
|
while a[j]>mid: j-=1
|
||||||
|
if i<=j:
|
||||||
|
a[i], a[j] = a[j], a[i]
|
||||||
|
i+=1
|
||||||
|
j-=1
|
||||||
|
__qsort(a, L, j)
|
||||||
|
__qsort(a, i, R)
|
||||||
|
|
||||||
|
def list::sort(self, reverse=False):
|
||||||
|
__qsort(self, 0, len(self)-1)
|
||||||
|
if reverse:
|
||||||
|
self.reverse()
|
||||||
|
|
||||||
|
def list::extend(self, other):
|
||||||
|
for i in other:
|
||||||
|
self.append(i)
|
||||||
|
|
||||||
|
def list::remove(self, value):
|
||||||
|
for i in range(len(self)):
|
||||||
|
if self[i] == value:
|
||||||
|
del self[i]
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def list::index(self, value):
|
||||||
|
for i in range(len(self)):
|
||||||
|
if self[i] == value:
|
||||||
|
return i
|
||||||
|
return -1
|
||||||
|
|
||||||
|
def list::pop(self, i=-1):
|
||||||
|
res = self[i]
|
||||||
|
del self[i]
|
||||||
|
return res
|
||||||
|
|
||||||
|
def list::__eq__(self, other):
|
||||||
|
if len(self) != len(other):
|
||||||
|
return False
|
||||||
|
for i in range(len(self)):
|
||||||
|
if self[i] != other[i]:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
tuple.__eq__ = list.__eq__
|
||||||
|
list.__ne__ = lambda self, other: not self.__eq__(other)
|
||||||
|
tuple.__ne__ = lambda self, other: not self.__eq__(other)
|
||||||
|
|
||||||
|
def list::count(self, x):
|
||||||
|
res = 0
|
||||||
|
for i in self:
|
||||||
|
if i == x:
|
||||||
|
res += 1
|
||||||
|
return res
|
||||||
|
tuple.count = list.count
|
||||||
|
|
||||||
|
def list::__contains__(self, item):
|
||||||
|
for i in self:
|
||||||
|
if i == item:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
tuple.__contains__ = list.__contains__
|
||||||
|
|
||||||
|
|
||||||
|
class property:
|
||||||
|
def __init__(self, fget):
|
||||||
|
self.fget = fget
|
||||||
|
|
||||||
|
def __get__(self, obj):
|
||||||
|
return self.fget(obj)
|
100
python/dict.py
Normal file
100
python/dict.py
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
class dict:
|
||||||
|
def __init__(self, capacity=13):
|
||||||
|
self._capacity = capacity
|
||||||
|
self._a = [None] * self._capacity
|
||||||
|
self._len = 0
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return self._len
|
||||||
|
|
||||||
|
def __probe(self, key):
|
||||||
|
i = hash(key) % self._capacity
|
||||||
|
while self._a[i] is not None:
|
||||||
|
if self._a[i][0] == key:
|
||||||
|
return True, i
|
||||||
|
i = (i + 1) % self._capacity
|
||||||
|
return False, i
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
ok, i = self.__probe(key)
|
||||||
|
if not ok:
|
||||||
|
raise KeyError(repr(key))
|
||||||
|
return self._a[i][1]
|
||||||
|
|
||||||
|
def __contains__(self, key):
|
||||||
|
ok, i = self.__probe(key)
|
||||||
|
return ok
|
||||||
|
|
||||||
|
def __setitem__(self, key, value):
|
||||||
|
ok, i = self.__probe(key)
|
||||||
|
if ok:
|
||||||
|
self._a[i][1] = value
|
||||||
|
else:
|
||||||
|
self._a[i] = [key, value]
|
||||||
|
self._len += 1
|
||||||
|
if self._len > self._capacity * 0.67:
|
||||||
|
self._capacity *= 2
|
||||||
|
self.__rehash()
|
||||||
|
|
||||||
|
def __delitem__(self, key):
|
||||||
|
ok, i = self.__probe(key)
|
||||||
|
if not ok:
|
||||||
|
raise KeyError(repr(key))
|
||||||
|
self._a[i] = None
|
||||||
|
self._len -= 1
|
||||||
|
|
||||||
|
def __rehash(self):
|
||||||
|
old_a = self._a
|
||||||
|
self._a = [None] * self._capacity
|
||||||
|
self._len = 0
|
||||||
|
for kv in old_a:
|
||||||
|
if kv is not None:
|
||||||
|
self[kv[0]] = kv[1]
|
||||||
|
|
||||||
|
def get(self, key, default=None):
|
||||||
|
ok, i = self.__probe(key)
|
||||||
|
if ok:
|
||||||
|
return self._a[i][1]
|
||||||
|
return default
|
||||||
|
|
||||||
|
def keys(self):
|
||||||
|
for kv in self._a:
|
||||||
|
if kv is not None:
|
||||||
|
yield kv[0]
|
||||||
|
|
||||||
|
def values(self):
|
||||||
|
for kv in self._a:
|
||||||
|
if kv is not None:
|
||||||
|
yield kv[1]
|
||||||
|
|
||||||
|
def items(self):
|
||||||
|
for kv in self._a:
|
||||||
|
if kv is not None:
|
||||||
|
yield kv
|
||||||
|
|
||||||
|
def clear(self):
|
||||||
|
self._a = [None] * self._capacity
|
||||||
|
self._len = 0
|
||||||
|
|
||||||
|
def update(self, other):
|
||||||
|
for k, v in other.items():
|
||||||
|
self[k] = v
|
||||||
|
|
||||||
|
def copy(self):
|
||||||
|
d = dict()
|
||||||
|
for kv in self._a:
|
||||||
|
if kv is not None:
|
||||||
|
d[kv[0]] = kv[1]
|
||||||
|
return d
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
a = [repr(k)+': '+repr(v) for k,v in self.items()]
|
||||||
|
return '{'+ ', '.join(a) + '}'
|
||||||
|
|
||||||
|
def __json__(self):
|
||||||
|
a = []
|
||||||
|
for k,v in self.items():
|
||||||
|
if type(k) is not str:
|
||||||
|
raise TypeError('json keys must be strings, got ' + repr(k) )
|
||||||
|
a.append(k.__json__()+': '+v.__json__())
|
||||||
|
return '{'+ ', '.join(a) + '}'
|
9
python/functools.py
Normal file
9
python/functools.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
def cache(f):
|
||||||
|
def wrapper(*args):
|
||||||
|
if not hasattr(f, 'cache'):
|
||||||
|
f.cache = {}
|
||||||
|
key = args
|
||||||
|
if key not in f.cache:
|
||||||
|
f.cache[key] = f(*args)
|
||||||
|
return f.cache[key]
|
||||||
|
return wrapper
|
7
python/random.py
Normal file
7
python/random.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
def shuffle(L):
|
||||||
|
for i in range(len(L)):
|
||||||
|
j = randint(i, len(L) - 1)
|
||||||
|
L[i], L[j] = L[j], L[i]
|
||||||
|
|
||||||
|
def choice(L):
|
||||||
|
return L[randint(0, len(L) - 1)]
|
98
python/set.py
Normal file
98
python/set.py
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
class set:
|
||||||
|
def __init__(self, iterable=None):
|
||||||
|
iterable = iterable or []
|
||||||
|
self._a = {}
|
||||||
|
for item in iterable:
|
||||||
|
self.add(item)
|
||||||
|
|
||||||
|
def add(self, elem):
|
||||||
|
self._a[elem] = None
|
||||||
|
|
||||||
|
def discard(self, elem):
|
||||||
|
if elem in self._a:
|
||||||
|
del self._a[elem]
|
||||||
|
|
||||||
|
def remove(self, elem):
|
||||||
|
del self._a[elem]
|
||||||
|
|
||||||
|
def clear(self):
|
||||||
|
self._a.clear()
|
||||||
|
|
||||||
|
def update(self,other):
|
||||||
|
for elem in other:
|
||||||
|
self.add(elem)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self._a)
|
||||||
|
|
||||||
|
def copy(self):
|
||||||
|
return set(self._a.keys())
|
||||||
|
|
||||||
|
def __and__(self, other):
|
||||||
|
ret = set()
|
||||||
|
for elem in self:
|
||||||
|
if elem in other:
|
||||||
|
ret.add(elem)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def __or__(self, other):
|
||||||
|
ret = self.copy()
|
||||||
|
for elem in other:
|
||||||
|
ret.add(elem)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def __sub__(self, other):
|
||||||
|
ret = set()
|
||||||
|
for elem in self:
|
||||||
|
if elem not in other:
|
||||||
|
ret.add(elem)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def __xor__(self, other):
|
||||||
|
ret = set()
|
||||||
|
for elem in self:
|
||||||
|
if elem not in other:
|
||||||
|
ret.add(elem)
|
||||||
|
for elem in other:
|
||||||
|
if elem not in self:
|
||||||
|
ret.add(elem)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def union(self, other):
|
||||||
|
return self | other
|
||||||
|
|
||||||
|
def intersection(self, other):
|
||||||
|
return self & other
|
||||||
|
|
||||||
|
def difference(self, other):
|
||||||
|
return self - other
|
||||||
|
|
||||||
|
def symmetric_difference(self, other):
|
||||||
|
return self ^ other
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self.__xor__(other).__len__() == 0
|
||||||
|
|
||||||
|
def __ne__(self, other):
|
||||||
|
return self.__xor__(other).__len__() != 0
|
||||||
|
|
||||||
|
def isdisjoint(self, other):
|
||||||
|
return self.__and__(other).__len__() == 0
|
||||||
|
|
||||||
|
def issubset(self, other):
|
||||||
|
return self.__sub__(other).__len__() == 0
|
||||||
|
|
||||||
|
def issuperset(self, other):
|
||||||
|
return other.__sub__(self).__len__() == 0
|
||||||
|
|
||||||
|
def __contains__(self, elem):
|
||||||
|
return elem in self._a
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
if len(self) == 0:
|
||||||
|
return 'set()'
|
||||||
|
return '{'+ ', '.join([repr(i) for i in self._a.keys()]) + '}'
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return self._a.keys()
|
416
src/builtins.h
416
src/builtins.h
@ -1,416 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
const char* kBuiltinsCode = R"(
|
|
||||||
def print(*args, sep=' ', end='\n'):
|
|
||||||
s = sep.join([str(i) for i in args])
|
|
||||||
__sys_stdout_write(s + end)
|
|
||||||
|
|
||||||
def round(x, ndigits=0):
|
|
||||||
assert ndigits >= 0
|
|
||||||
if ndigits == 0:
|
|
||||||
return x >= 0 ? int(x + 0.5) : int(x - 0.5)
|
|
||||||
if x >= 0:
|
|
||||||
return int(x * 10**ndigits + 0.5) / 10**ndigits
|
|
||||||
else:
|
|
||||||
return int(x * 10**ndigits - 0.5) / 10**ndigits
|
|
||||||
|
|
||||||
def isinstance(obj, cls):
|
|
||||||
assert type(cls) is type
|
|
||||||
obj_t = type(obj)
|
|
||||||
while obj_t is not None:
|
|
||||||
if obj_t is cls:
|
|
||||||
return True
|
|
||||||
obj_t = obj_t.__base__
|
|
||||||
return False
|
|
||||||
|
|
||||||
def abs(x):
|
|
||||||
return x < 0 ? -x : x
|
|
||||||
|
|
||||||
def max(a, b):
|
|
||||||
return a > b ? a : b
|
|
||||||
|
|
||||||
def min(a, b):
|
|
||||||
return a < b ? a : b
|
|
||||||
|
|
||||||
def all(iterable):
|
|
||||||
for i in iterable:
|
|
||||||
if not i:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def any(iterable):
|
|
||||||
for i in iterable:
|
|
||||||
if i:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def enumerate(iterable, start=0):
|
|
||||||
n = start
|
|
||||||
for elem in iterable:
|
|
||||||
yield n, elem
|
|
||||||
n += 1
|
|
||||||
|
|
||||||
def sum(iterable):
|
|
||||||
res = 0
|
|
||||||
for i in iterable:
|
|
||||||
res += i
|
|
||||||
return res
|
|
||||||
|
|
||||||
def map(f, iterable):
|
|
||||||
for i in iterable:
|
|
||||||
yield f(i)
|
|
||||||
|
|
||||||
def zip(a, b):
|
|
||||||
for i in range(min(len(a), len(b))):
|
|
||||||
yield (a[i], b[i])
|
|
||||||
|
|
||||||
def reversed(iterable):
|
|
||||||
a = list(iterable)
|
|
||||||
a.reverse()
|
|
||||||
return a
|
|
||||||
|
|
||||||
def sorted(iterable, reverse=False):
|
|
||||||
a = list(iterable)
|
|
||||||
a.sort(reverse=reverse)
|
|
||||||
return a
|
|
||||||
|
|
||||||
##### str #####
|
|
||||||
|
|
||||||
str.__mul__ = lambda self, n: ''.join([self for _ in range(n)])
|
|
||||||
|
|
||||||
def str::split(self, sep):
|
|
||||||
if sep == "":
|
|
||||||
return list(self)
|
|
||||||
res = []
|
|
||||||
i = 0
|
|
||||||
while i < len(self):
|
|
||||||
if self[i:i+len(sep)] == sep:
|
|
||||||
res.append(self[:i])
|
|
||||||
self = self[i+len(sep):]
|
|
||||||
i = 0
|
|
||||||
else:
|
|
||||||
i += 1
|
|
||||||
res.append(self)
|
|
||||||
return res
|
|
||||||
|
|
||||||
def str::index(self, sub):
|
|
||||||
for i in range(len(self)):
|
|
||||||
if self[i:i+len(sub)] == sub:
|
|
||||||
return i
|
|
||||||
return -1
|
|
||||||
|
|
||||||
def str::strip(self, chars=None):
|
|
||||||
chars = chars or ' \t\n\r'
|
|
||||||
i = 0
|
|
||||||
while i < len(self) and self[i] in chars:
|
|
||||||
i += 1
|
|
||||||
j = len(self) - 1
|
|
||||||
while j >= 0 and self[j] in chars:
|
|
||||||
j -= 1
|
|
||||||
return self[i:j+1]
|
|
||||||
|
|
||||||
##### list #####
|
|
||||||
|
|
||||||
list.__repr__ = lambda self: '[' + ', '.join([repr(i) for i in self]) + ']'
|
|
||||||
tuple.__repr__ = lambda self: '(' + ', '.join([repr(i) for i in self]) + ')'
|
|
||||||
list.__json__ = lambda self: '[' + ', '.join([i.__json__() for i in self]) + ']'
|
|
||||||
tuple.__json__ = lambda self: '[' + ', '.join([i.__json__() for i in self]) + ']'
|
|
||||||
|
|
||||||
def __qsort(a: list, L: int, R: int):
|
|
||||||
if L >= R: return;
|
|
||||||
mid = a[(R+L)//2];
|
|
||||||
i, j = L, R
|
|
||||||
while i<=j:
|
|
||||||
while a[i]<mid: i+=1
|
|
||||||
while a[j]>mid: j-=1
|
|
||||||
if i<=j:
|
|
||||||
a[i], a[j] = a[j], a[i]
|
|
||||||
i+=1
|
|
||||||
j-=1
|
|
||||||
__qsort(a, L, j)
|
|
||||||
__qsort(a, i, R)
|
|
||||||
|
|
||||||
def list::sort(self, reverse=False):
|
|
||||||
__qsort(self, 0, len(self)-1)
|
|
||||||
if reverse:
|
|
||||||
self.reverse()
|
|
||||||
|
|
||||||
def list::extend(self, other):
|
|
||||||
for i in other:
|
|
||||||
self.append(i)
|
|
||||||
|
|
||||||
def list::remove(self, value):
|
|
||||||
for i in range(len(self)):
|
|
||||||
if self[i] == value:
|
|
||||||
del self[i]
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def list::index(self, value):
|
|
||||||
for i in range(len(self)):
|
|
||||||
if self[i] == value:
|
|
||||||
return i
|
|
||||||
return -1
|
|
||||||
|
|
||||||
def list::pop(self, i=-1):
|
|
||||||
res = self[i]
|
|
||||||
del self[i]
|
|
||||||
return res
|
|
||||||
|
|
||||||
def list::__eq__(self, other):
|
|
||||||
if len(self) != len(other):
|
|
||||||
return False
|
|
||||||
for i in range(len(self)):
|
|
||||||
if self[i] != other[i]:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
tuple.__eq__ = list.__eq__
|
|
||||||
list.__ne__ = lambda self, other: not self.__eq__(other)
|
|
||||||
tuple.__ne__ = lambda self, other: not self.__eq__(other)
|
|
||||||
|
|
||||||
def list::count(self, x):
|
|
||||||
res = 0
|
|
||||||
for i in self:
|
|
||||||
if i == x:
|
|
||||||
res += 1
|
|
||||||
return res
|
|
||||||
tuple.count = list.count
|
|
||||||
|
|
||||||
def list::__contains__(self, item):
|
|
||||||
for i in self:
|
|
||||||
if i == item:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
tuple.__contains__ = list.__contains__
|
|
||||||
list.__new__ = lambda obj: [i for i in obj]
|
|
||||||
|
|
||||||
class dict:
|
|
||||||
def __init__(self, capacity=13):
|
|
||||||
self._capacity = capacity
|
|
||||||
self._a = [None] * self._capacity
|
|
||||||
self._len = 0
|
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
return self._len
|
|
||||||
|
|
||||||
def __probe(self, key):
|
|
||||||
i = hash(key) % self._capacity
|
|
||||||
while self._a[i] is not None:
|
|
||||||
if self._a[i][0] == key:
|
|
||||||
return True, i
|
|
||||||
i = (i + 1) % self._capacity
|
|
||||||
return False, i
|
|
||||||
|
|
||||||
def __getitem__(self, key):
|
|
||||||
ok, i = self.__probe(key)
|
|
||||||
if not ok:
|
|
||||||
raise KeyError(repr(key))
|
|
||||||
return self._a[i][1]
|
|
||||||
|
|
||||||
def __contains__(self, key):
|
|
||||||
ok, i = self.__probe(key)
|
|
||||||
return ok
|
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
|
||||||
ok, i = self.__probe(key)
|
|
||||||
if ok:
|
|
||||||
self._a[i][1] = value
|
|
||||||
else:
|
|
||||||
self._a[i] = [key, value]
|
|
||||||
self._len += 1
|
|
||||||
if self._len > self._capacity * 0.67:
|
|
||||||
self._capacity *= 2
|
|
||||||
self.__rehash()
|
|
||||||
|
|
||||||
def __delitem__(self, key):
|
|
||||||
ok, i = self.__probe(key)
|
|
||||||
if not ok:
|
|
||||||
raise KeyError(repr(key))
|
|
||||||
self._a[i] = None
|
|
||||||
self._len -= 1
|
|
||||||
|
|
||||||
def __rehash(self):
|
|
||||||
old_a = self._a
|
|
||||||
self._a = [None] * self._capacity
|
|
||||||
self._len = 0
|
|
||||||
for kv in old_a:
|
|
||||||
if kv is not None:
|
|
||||||
self[kv[0]] = kv[1]
|
|
||||||
|
|
||||||
def get(self, key, default=None):
|
|
||||||
ok, i = self.__probe(key)
|
|
||||||
if ok:
|
|
||||||
return self._a[i][1]
|
|
||||||
return default
|
|
||||||
|
|
||||||
def keys(self):
|
|
||||||
for kv in self._a:
|
|
||||||
if kv is not None:
|
|
||||||
yield kv[0]
|
|
||||||
|
|
||||||
def values(self):
|
|
||||||
for kv in self._a:
|
|
||||||
if kv is not None:
|
|
||||||
yield kv[1]
|
|
||||||
|
|
||||||
def items(self):
|
|
||||||
for kv in self._a:
|
|
||||||
if kv is not None:
|
|
||||||
yield kv
|
|
||||||
|
|
||||||
def clear(self):
|
|
||||||
self._a = [None] * self._capacity
|
|
||||||
self._len = 0
|
|
||||||
|
|
||||||
def update(self, other):
|
|
||||||
for k, v in other.items():
|
|
||||||
self[k] = v
|
|
||||||
|
|
||||||
def copy(self):
|
|
||||||
d = dict()
|
|
||||||
for kv in self._a:
|
|
||||||
if kv is not None:
|
|
||||||
d[kv[0]] = kv[1]
|
|
||||||
return d
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
a = [repr(k)+': '+repr(v) for k,v in self.items()]
|
|
||||||
return '{'+ ', '.join(a) + '}'
|
|
||||||
|
|
||||||
def __json__(self):
|
|
||||||
a = []
|
|
||||||
for k,v in self.items():
|
|
||||||
if type(k) is not str:
|
|
||||||
raise TypeError('json keys must be strings, got ' + repr(k) )
|
|
||||||
a.append(k.__json__()+': '+v.__json__())
|
|
||||||
return '{'+ ', '.join(a) + '}'
|
|
||||||
|
|
||||||
class set:
|
|
||||||
def __init__(self, iterable=None):
|
|
||||||
iterable = iterable or []
|
|
||||||
self._a = dict()
|
|
||||||
for item in iterable:
|
|
||||||
self.add(item)
|
|
||||||
|
|
||||||
def add(self, elem):
|
|
||||||
self._a[elem] = None
|
|
||||||
|
|
||||||
def discard(self, elem):
|
|
||||||
if elem in self._a:
|
|
||||||
del self._a[elem]
|
|
||||||
|
|
||||||
def remove(self, elem):
|
|
||||||
del self._a[elem]
|
|
||||||
|
|
||||||
def clear(self):
|
|
||||||
self._a.clear()
|
|
||||||
|
|
||||||
def update(self,other):
|
|
||||||
for elem in other:
|
|
||||||
self.add(elem)
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
return len(self._a)
|
|
||||||
|
|
||||||
def copy(self):
|
|
||||||
return set(self._a.keys())
|
|
||||||
|
|
||||||
def __and__(self, other):
|
|
||||||
ret = set()
|
|
||||||
for elem in self:
|
|
||||||
if elem in other:
|
|
||||||
ret.add(elem)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def __or__(self, other):
|
|
||||||
ret = self.copy()
|
|
||||||
for elem in other:
|
|
||||||
ret.add(elem)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def __sub__(self, other):
|
|
||||||
ret = set()
|
|
||||||
for elem in self:
|
|
||||||
if elem not in other:
|
|
||||||
ret.add(elem)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def __xor__(self, other):
|
|
||||||
ret = set()
|
|
||||||
for elem in self:
|
|
||||||
if elem not in other:
|
|
||||||
ret.add(elem)
|
|
||||||
for elem in other:
|
|
||||||
if elem not in self:
|
|
||||||
ret.add(elem)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def union(self, other):
|
|
||||||
return self | other
|
|
||||||
|
|
||||||
def intersection(self, other):
|
|
||||||
return self & other
|
|
||||||
|
|
||||||
def difference(self, other):
|
|
||||||
return self - other
|
|
||||||
|
|
||||||
def symmetric_difference(self, other):
|
|
||||||
return self ^ other
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
return self.__xor__(other).__len__() == 0
|
|
||||||
|
|
||||||
def __ne__(self, other):
|
|
||||||
return self.__xor__(other).__len__() != 0
|
|
||||||
|
|
||||||
def isdisjoint(self, other):
|
|
||||||
return self.__and__(other).__len__() == 0
|
|
||||||
|
|
||||||
def issubset(self, other):
|
|
||||||
return self.__sub__(other).__len__() == 0
|
|
||||||
|
|
||||||
def issuperset(self, other):
|
|
||||||
return other.__sub__(self).__len__() == 0
|
|
||||||
|
|
||||||
def __contains__(self, elem):
|
|
||||||
return elem in self._a
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
if len(self) == 0:
|
|
||||||
return 'set()'
|
|
||||||
return '{'+ ', '.join([repr(i) for i in self._a.keys()]) + '}'
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
return self._a.keys()
|
|
||||||
|
|
||||||
class property:
|
|
||||||
def __init__(self, fget):
|
|
||||||
self.fget = fget
|
|
||||||
|
|
||||||
def __get__(self, obj):
|
|
||||||
return self.fget(obj)
|
|
||||||
)";
|
|
||||||
|
|
||||||
const char* kRandomCode = R"(
|
|
||||||
def shuffle(L):
|
|
||||||
for i in range(len(L)):
|
|
||||||
j = randint(i, len(L) - 1)
|
|
||||||
L[i], L[j] = L[j], L[i]
|
|
||||||
|
|
||||||
def choice(L):
|
|
||||||
return L[randint(0, len(L) - 1)]
|
|
||||||
)";
|
|
||||||
|
|
||||||
const char* kFuncToolsCode = R"(
|
|
||||||
def cache(f):
|
|
||||||
def wrapper(*args):
|
|
||||||
if not hasattr(f, 'cache'):
|
|
||||||
f.cache = {}
|
|
||||||
key = args
|
|
||||||
if key not in f.cache:
|
|
||||||
f.cache[key] = f(*args)
|
|
||||||
return f.cache[key]
|
|
||||||
return wrapper
|
|
||||||
)";
|
|
@ -5,6 +5,7 @@
|
|||||||
#include "repl.h"
|
#include "repl.h"
|
||||||
#include "iter.h"
|
#include "iter.h"
|
||||||
#include "cffi.h"
|
#include "cffi.h"
|
||||||
|
#include "_generated.h"
|
||||||
|
|
||||||
namespace pkpy {
|
namespace pkpy {
|
||||||
|
|
||||||
@ -534,8 +535,6 @@ void init_builtins(VM* _vm) {
|
|||||||
_vm->bind_method<0>("ellipsis", "__repr__", CPP_LAMBDA(VAR("Ellipsis")));
|
_vm->bind_method<0>("ellipsis", "__repr__", CPP_LAMBDA(VAR("Ellipsis")));
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "builtins.h"
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define __EXPORT __declspec(dllexport)
|
#define __EXPORT __declspec(dllexport)
|
||||||
#elif __APPLE__
|
#elif __APPLE__
|
||||||
@ -773,13 +772,13 @@ void add_module_random(VM* vm){
|
|||||||
return VAR(a + (b - a) * std::rand() / (f64)RAND_MAX);
|
return VAR(a + (b - a) * std::rand() / (f64)RAND_MAX);
|
||||||
});
|
});
|
||||||
|
|
||||||
CodeObject_ code = vm->compile(kRandomCode, "random.py", EXEC_MODE);
|
CodeObject_ code = vm->compile(kPythonLibs["random"], "random.py", EXEC_MODE);
|
||||||
vm->_exec(code, mod);
|
vm->_exec(code, mod);
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_module_functools(VM* vm){
|
void add_module_functools(VM* vm){
|
||||||
PyVar mod = vm->new_module("functools");
|
PyVar mod = vm->new_module("functools");
|
||||||
CodeObject_ code = vm->compile(kFuncToolsCode, "functools.py", EXEC_MODE);
|
CodeObject_ code = vm->compile(kPythonLibs["functools"], "functools.py", EXEC_MODE);
|
||||||
vm->_exec(code, mod);
|
vm->_exec(code, mod);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -797,7 +796,11 @@ void VM::post_init(){
|
|||||||
add_module_functools(this);
|
add_module_functools(this);
|
||||||
add_module_c(this);
|
add_module_c(this);
|
||||||
|
|
||||||
CodeObject_ code = compile(kBuiltinsCode, "<builtins>", EXEC_MODE);
|
CodeObject_ code = compile(kPythonLibs["builtins"], "<builtins>", EXEC_MODE);
|
||||||
|
this->_exec(code, this->builtins);
|
||||||
|
code = compile(kPythonLibs["dict"], "<builtins>", EXEC_MODE);
|
||||||
|
this->_exec(code, this->builtins);
|
||||||
|
code = compile(kPythonLibs["set"], "<builtins>", EXEC_MODE);
|
||||||
this->_exec(code, this->builtins);
|
this->_exec(code, this->builtins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user