From 3b13b1a9883a73af51deb8bd757036cf3b324e3e Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 5 Mar 2023 01:54:34 +0800 Subject: [PATCH] up Update build.py up up --- .github/workflows/main.yml | 11 +- .gitignore | 2 + amalgamate.py | 8 +- build.py | 50 +++++ build_cpp.sh | 1 - build_linux.sh | 3 - build_wasm.sh | 3 - compile_flags.txt | 3 +- preprocess.py | 36 ++++ profile.sh | 7 - python/builtins.py | 190 +++++++++++++++++ python/dict.py | 100 +++++++++ python/functools.py | 9 + python/random.py | 7 + python/set.py | 98 +++++++++ src/builtins.h | 416 ------------------------------------- src/pocketpy.h | 13 +- 17 files changed, 513 insertions(+), 444 deletions(-) create mode 100644 build.py delete mode 100644 build_cpp.sh delete mode 100644 build_linux.sh delete mode 100644 build_wasm.sh create mode 100644 preprocess.py delete mode 100644 profile.sh create mode 100644 python/builtins.py create mode 100644 python/dict.py create mode 100644 python/functools.py create mode 100644 python/random.py create mode 100644 python/set.py delete mode 100644 src/builtins.h diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 53a7bccf..26d3e33d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -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 diff --git a/.gitignore b/.gitignore index 410b3d99..26057a57 100644 --- a/.gitignore +++ b/.gitignore @@ -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 \ No newline at end of file diff --git a/amalgamate.py b/amalgamate.py index 6bff82ae..39a74d4a 100644 --- a/amalgamate.py +++ b/amalgamate.py @@ -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() diff --git a/build.py b/build.py new file mode 100644 index 00000000..c64586dc --- /dev/null +++ b/build.py @@ -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() \ No newline at end of file diff --git a/build_cpp.sh b/build_cpp.sh deleted file mode 100644 index 571cb192..00000000 --- a/build_cpp.sh +++ /dev/null @@ -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 \ No newline at end of file diff --git a/build_linux.sh b/build_linux.sh deleted file mode 100644 index 7f06d5de..00000000 --- a/build_linux.sh +++ /dev/null @@ -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 \ No newline at end of file diff --git a/build_wasm.sh b/build_wasm.sh deleted file mode 100644 index a6159f80..00000000 --- a/build_wasm.sh +++ /dev/null @@ -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 \ No newline at end of file diff --git a/compile_flags.txt b/compile_flags.txt index 8667be6c..eece4aaf 100644 --- a/compile_flags.txt +++ b/compile_flags.txt @@ -1,4 +1,5 @@ -xc++ -Wall -W* --std=c++17 \ No newline at end of file +-std=c++17 +-stdlib=libc++ \ No newline at end of file diff --git a/preprocess.py b/preprocess.py new file mode 100644 index 00000000..492e8bd1 --- /dev/null +++ b/preprocess.py @@ -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 +#include + +namespace pkpy{ + std::map 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()) \ No newline at end of file diff --git a/profile.sh b/profile.sh deleted file mode 100644 index 80e9ff2c..00000000 --- a/profile.sh +++ /dev/null @@ -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 \ No newline at end of file diff --git a/python/builtins.py b/python/builtins.py new file mode 100644 index 00000000..9a3c3097 --- /dev/null +++ b/python/builtins.py @@ -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: 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) \ No newline at end of file diff --git a/python/dict.py b/python/dict.py new file mode 100644 index 00000000..311715b5 --- /dev/null +++ b/python/dict.py @@ -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) + '}' \ No newline at end of file diff --git a/python/functools.py b/python/functools.py new file mode 100644 index 00000000..81e517fa --- /dev/null +++ b/python/functools.py @@ -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 \ No newline at end of file diff --git a/python/random.py b/python/random.py new file mode 100644 index 00000000..5fdcfcc6 --- /dev/null +++ b/python/random.py @@ -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)] \ No newline at end of file diff --git a/python/set.py b/python/set.py new file mode 100644 index 00000000..934f4c27 --- /dev/null +++ b/python/set.py @@ -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() \ No newline at end of file diff --git a/src/builtins.h b/src/builtins.h deleted file mode 100644 index ac875eec..00000000 --- a/src/builtins.h +++ /dev/null @@ -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: 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 -)"; \ No newline at end of file diff --git a/src/pocketpy.h b/src/pocketpy.h index a453d489..9270548a 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -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, "", EXEC_MODE); + CodeObject_ code = compile(kPythonLibs["builtins"], "", EXEC_MODE); + this->_exec(code, this->builtins); + code = compile(kPythonLibs["dict"], "", EXEC_MODE); + this->_exec(code, this->builtins); + code = compile(kPythonLibs["set"], "", EXEC_MODE); this->_exec(code, this->builtins); }