blueloveTH 1 年之前
父节点
当前提交
57574bd8be
共有 2 个文件被更改,包括 128 次插入0 次删除
  1. 114 0
      docs/features/precompile.md
  2. 14 0
      tests/94_compile.py

+ 114 - 0
docs/features/precompile.md

@@ -0,0 +1,114 @@
+---
+icon: dot
+title: Precompiling
+---
+
+pkpy allows you to precompile your python code into a special form, which can be executed later.
+
+### In-memory precompilation
+
+You can use `vm->compile` to compile your source code into a `CodeObject_` object.
+This object can be executed later by `vm->_exec`.
+
+```cpp
+CodeObject_ code = vm->compile("print('Hello, world!')", "<string>", EXEC_MODE);
+vm->_exec(code);        // Hello, world!
+```
+
+This `CodeObject_` object is a very non-generic form of the compiled code.
+It is an in-memory form. You are not able to save it to a file or load it from a file.
+
+
+### String precompilation
+
+In order to save the compiled code to a file, you need to use `vm->precompile`.
+It does some basic preprocessing and outputs the result as a human-readable string.
+
+```cpp
+// precompile the source code into a string
+Str source = vm->precompile("print('Hello, world!')", "<string>", EXEC_MODE);
+
+CodeObject code = vm->compile(source, "<string>", EXEC_MODE);
+vm->_exec(code);        // Hello, world!
+```
+
+You can also use python's `compile` function to achieve the same effect.
+
+```python
+code = compile("print('Hello, world!')", "<string>", "exec")
+exec(code)        # Hello, world!
+```
+
+Let's take a look at the precompiled string.
+```python
+print(code)
+```
+
+```txt
+pkpy:1.4.4
+0
+|print|
+=6
+5,1,0,
+6,1,5,1,0,
+42,1,1,
+8,1,1,S48656c6c6f2c20776f726c6421
+43,1,0,
+3,1,0,
+
+```
+
+Comparing with **In-memory precompilation**,
+**String precompilation** drops most of the original source code.
+It has an encryption effect, which can protect your source code from being stolen.
+It also means there is no source line information when an error occurs.
+
+```python
+src = """
+def f(a, b):
+    return g(a, b)
+
+def g(a, b):
+    c = f(a, b)
+    d = g(a, b)
+    return c + d
+"""
+
+code = compile(src, "<exec>", "exec")
+exec(code)
+f(1, 2)
+```
+
+You will get this (without source line information):
+```txt
+Traceback (most recent call last):
+  File "<exec>", line 3, in f
+  File "<exec>", line 6, in g
+  File "<exec>", line 3, in f
+  File "<exec>", line 6, in g
+  File "<exec>", line 3, in f
+  File "<exec>", line 6, in g
+  File "<exec>", line 3, in f
+StackOverflowError
+```
+
+instead of this (with source line information):
+
+```txt
+Traceback (most recent call last):
+  File "<stdin>", line 2, in f
+    return g(a, b)
+  File "<stdin>", line 2, in g
+    c = f(a, b)
+  File "<stdin>", line 2, in f
+    return g(a, b)
+  File "<stdin>", line 2, in g
+    c = f(a, b)
+  File "<stdin>", line 2, in f
+    return g(a, b)
+  File "<stdin>", line 2, in g
+    c = f(a, b)
+  File "<stdin>", line 2, in f
+    return g(a, b)
+StackOverflowError
+```

+ 14 - 0
tests/94_compile.py

@@ -1,2 +1,16 @@
 code = compile("1+2", "<eval>", "eval")
 assert eval(code) == 3
+
+src = """
+def f(a, b):
+    return g(a, b)
+
+def g(a, b):
+    c = f(a, b)
+    d = g(a, b)
+    return c + d
+"""
+
+code = compile(src, "<12>", "exec")
+exec(code)
+f(1, 2)