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
|
||||
shell: bash
|
||||
run: |
|
||||
clang-cl.exe -std:c++17 -GR- -EHsc -O2 -Wno-deprecated-declarations -Fe:pocketpy src/main.cpp
|
||||
echo '#include "pocketpy.h"' > src/tmp.cpp
|
||||
clang-cl.exe -std:c++17 -GR- -EHsc -O2 -Wno-deprecated-declarations -LD -Fe:pocketpy src/tmp.cpp
|
||||
python3 build.py windows
|
||||
python3 build.py windows -lib
|
||||
python3 scripts/run_tests.py
|
||||
python3 scripts/run_tests.py benchmark
|
||||
mkdir -p output/windows/x86_64
|
||||
@ -38,7 +37,7 @@ jobs:
|
||||
- name: Compiling
|
||||
run: |
|
||||
mkdir -p output/web/lib
|
||||
bash build_wasm.sh
|
||||
python3 build.py web
|
||||
cp web/lib/* output/web/lib
|
||||
- uses: crazy-max/ghaction-github-pages@v3
|
||||
with:
|
||||
@ -62,8 +61,8 @@ jobs:
|
||||
- name: Compiling
|
||||
run: |
|
||||
sudo apt install -y libc++-15-dev libc++1-15 libc++abi-15-dev libc++abi1-15
|
||||
bash build_cpp.sh
|
||||
bash build_linux.sh
|
||||
python3 build.py linux
|
||||
python3 build.py linux -lib
|
||||
python3 scripts/run_tests.py
|
||||
python3 scripts/run_tests.py benchmark
|
||||
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/godot/godot-cpp/
|
||||
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:
|
||||
OPCODES_TEXT = f.read()
|
||||
|
||||
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"],
|
||||
["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()
|
||||
|
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
|
@ -1,4 +1,5 @@
|
||||
-xc++
|
||||
-Wall
|
||||
-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 "iter.h"
|
||||
#include "cffi.h"
|
||||
#include "_generated.h"
|
||||
|
||||
namespace pkpy {
|
||||
|
||||
@ -534,8 +535,6 @@ void init_builtins(VM* _vm) {
|
||||
_vm->bind_method<0>("ellipsis", "__repr__", CPP_LAMBDA(VAR("Ellipsis")));
|
||||
}
|
||||
|
||||
#include "builtins.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define __EXPORT __declspec(dllexport)
|
||||
#elif __APPLE__
|
||||
@ -773,13 +772,13 @@ void add_module_random(VM* vm){
|
||||
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);
|
||||
}
|
||||
|
||||
void add_module_functools(VM* vm){
|
||||
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);
|
||||
}
|
||||
|
||||
@ -797,7 +796,11 @@ void VM::post_init(){
|
||||
add_module_functools(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);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user