Compare commits

...

140 Commits

Author SHA1 Message Date
xushiwei
2a35ffcc27 Merge pull request #184 from xushiwei/q
README
2024-05-16 00:06:24 +08:00
xushiwei
5eae8f9af6 README 2024-05-16 00:02:10 +08:00
xushiwei
25381e20d2 TestSqlite 2024-05-15 21:43:38 +08:00
xushiwei
fc35ff5cd1 Merge pull request #182 from xushiwei/q
sqlite demo
2024-05-15 21:39:00 +08:00
xushiwei
b10d00b426 rm TestSqlite 2024-05-15 21:36:48 +08:00
xushiwei
c634dc25b4 sqlite demo 2024-05-15 21:27:42 +08:00
xushiwei
2fb4561bf8 Merge pull request #181 from xushiwei/q
rm submodule sqlite
2024-05-15 21:14:10 +08:00
xushiwei
f167c6dcca rm submodule sqlite 2024-05-15 21:12:58 +08:00
xushiwei
555ace9e2e Merge pull request #179 from xushiwei/q
llgo/ssa: PyNewVar; pyLoad
2024-05-15 18:49:10 +08:00
xushiwei
d07ffb36ad TestUserdefExpr: pyVarTy 2024-05-15 18:45:53 +08:00
xushiwei
9e2b8b77c9 py/math: remove vars 2024-05-15 18:40:54 +08:00
xushiwei
29e4af4fb2 llgo/ssa: PyNewVar; pyLoad 2024-05-15 18:32:50 +08:00
xushiwei
91513a12b4 llgo/ssa: refactor python related names (PyXXX) 2024-05-15 17:19:47 +08:00
xushiwei
ee3f55dd41 compileGlobal: skip pyVar 2024-05-15 16:51:44 +08:00
xushiwei
c2e5a78076 compileFuncDecl remove param: call bool 2024-05-15 16:40:10 +08:00
xushiwei
da3ac3e93d Merge pull request #178 from xushiwei/q
README: python support
2024-05-15 16:05:01 +08:00
xushiwei
278ebbc9bd README: python support 2024-05-15 16:04:20 +08:00
xushiwei
546f93147e Merge pull request #177 from xushiwei/q
llgo instr: pyList
2024-05-15 15:46:18 +08:00
xushiwei
3e7bfbb45c llgo instr: pyList 2024-05-15 15:42:58 +08:00
xushiwei
c2cf0443ef Merge remote-tracking branch 'gop/main' into q 2024-05-15 14:49:25 +08:00
xushiwei
59d68c6438 llgo/ssa: PyList 2024-05-15 14:49:00 +08:00
xushiwei
e0ee199bf1 Merge pull request #176 from xushiwei/q
numpy demo: _pydemo/matrix
2024-05-15 13:59:43 +08:00
xushiwei
c1bf895674 llpyg: numpy/inspect 2024-05-15 13:57:26 +08:00
xushiwei
ea4d92e671 py/os fix 2024-05-15 13:51:58 +08:00
xushiwei
e3f56105d4 numpy demo: _pydemo/matrix 2024-05-15 13:49:19 +08:00
xushiwei
c447a87605 Merge pull request #175 from xushiwei/q
cl: _testpy/gcd
2024-05-15 13:33:56 +08:00
xushiwei
584e5b1f01 TestPrintf fix 2024-05-15 13:30:48 +08:00
xushiwei
207dc4c112 Merge pull request #174 from visualfc/append
ssa: add builtin append
2024-05-15 13:27:58 +08:00
xushiwei
6a3581f7a3 goTypes.cvtFunc fix: remove sig.Variadic flag 2024-05-15 13:24:44 +08:00
xushiwei
11e74975b3 llgo/ssa: rm HasVArg/IsVArg 2024-05-15 13:09:43 +08:00
xushiwei
75ef9ec524 x 2024-05-15 12:01:36 +08:00
xushiwei
9b742e777b cl: _testpy/gcd 2024-05-15 11:59:53 +08:00
visualfc
5d93565e16 ssa: add builtin append 2024-05-15 10:43:26 +08:00
xushiwei
cebfe5c95b Merge pull request #173 from xushiwei/q
cl: _testpy/pow (multiargs)
2024-05-15 08:57:09 +08:00
xushiwei
7881f3a53b x 2024-05-15 08:54:29 +08:00
xushiwei
56269bd52b cl: _testpy/pow (multiargs) 2024-05-15 08:44:00 +08:00
xushiwei
68c43a2cc9 Merge pull request #172 from xushiwei/q
py/numpy
2024-05-15 00:33:10 +08:00
xushiwei
120b507c75 numpy: array, etc 2024-05-15 00:29:54 +08:00
xushiwei
44fe7e8dc4 py/numpy 2024-05-14 23:56:55 +08:00
xushiwei
75d679f141 Merge pull request #171 from xushiwei/q
py/sys; llpyg: prompt import mod fail; py: fix typo
2024-05-14 22:36:03 +08:00
xushiwei
e9570f2400 llpyg: prompt import mod fail; py: fix typo 2024-05-14 22:33:36 +08:00
xushiwei
5b8567310c Merge pull request #170 from xushiwei/q
py/json, py/statistics; demo: statistics.mean
2024-05-14 21:08:14 +08:00
xushiwei
f882221db3 py/math 2024-05-14 21:06:25 +08:00
xushiwei
8c4d7bd641 py/json, py/statistics; demo: statistics.mean 2024-05-14 20:53:13 +08:00
xushiwei
6a78695fde Merge pull request #169 from xushiwei/q
llpyg fix: handle / in sig; llpyg math
2024-05-14 20:17:24 +08:00
xushiwei
73ad16dedd llpyg fix: handle / in sig 2024-05-14 20:14:59 +08:00
xushiwei
dd98112c5a Merge pull request #168 from xushiwei/q
llpyg os
2024-05-14 19:40:49 +08:00
xushiwei
47521d3579 llpyg fix: empty params 2024-05-14 19:38:30 +08:00
xushiwei
0c31300578 llpyg os 2024-05-14 19:19:46 +08:00
xushiwei
6340ff7da0 Merge pull request #166 from visualfc/stringcat
ssa: fix binop string cat ret type
2024-05-14 18:23:51 +08:00
xushiwei
b66cb49d80 Merge pull request #167 from xushiwei/q
llpyg
2024-05-14 18:22:41 +08:00
xushiwei
c884184220 py llgen 2024-05-14 18:19:44 +08:00
xushiwei
091fee61e0 llpyg: pkg.NewFuncDecl 2024-05-14 18:16:32 +08:00
xushiwei
172a268e77 llpyg: ready to test 2024-05-14 17:22:36 +08:00
visualfc
924715fe34 ssa: fix binop string cat ret type 2024-05-14 15:58:33 +08:00
xushiwei
35a73b4cde llpyg: todo 2024-05-14 15:34:53 +08:00
xushiwei
238f9593f9 Update README.md 2024-05-14 13:34:47 +08:00
xushiwei
9e8b5703dc Merge pull request #165 from xushiwei/q
llpyg => pydump
2024-05-14 13:27:51 +08:00
xushiwei
d8bd8be57e llpyg => pydump 2024-05-14 13:23:21 +08:00
xushiwei
a4d4e8b3a9 Merge pull request #164 from xushiwei/q
llgo/x/cjson
2024-05-14 11:52:22 +08:00
xushiwei
703dd17e33 llgo/x/cjson 2024-05-14 11:49:37 +08:00
xushiwei
bc654a462e Merge pull request #162 from xushiwei/q
build: support packages out of llgo
2024-05-14 08:49:11 +08:00
xushiwei
11535825c0 build: support packages out of llgo 2024-05-14 08:40:42 +08:00
xushiwei
196df40c99 Merge pull request #161 from xushiwei/q
llpyg sig fix
2024-05-14 00:34:58 +08:00
xushiwei
7aee6c3a15 llpyg sig fix 2024-05-14 00:31:30 +08:00
xushiwei
372b566d23 mv _xtool => chore/_xtool 2024-05-13 23:03:54 +08:00
xushiwei
9550354442 Merge pull request #160 from xushiwei/q
llpyg: todo
2024-05-13 22:12:17 +08:00
xushiwei
95c3ddfc39 math 2024-05-13 22:05:49 +08:00
xushiwei
bf4f2b6fa0 py/builtins: todo 2024-05-13 22:02:47 +08:00
xushiwei
d3f75a92ad llpyg: print doc 2024-05-13 21:01:39 +08:00
xushiwei
369495c8d3 Merge pull request #159 from xushiwei/q
llpyg: use inspect.Signature
2024-05-13 19:51:05 +08:00
xushiwei
dd52f71069 llpyg: use inspect.Signature 2024-05-13 19:48:33 +08:00
xushiwei
af8e2bc19d Merge pull request #158 from xushiwei/q
_xtool: llpyg
2024-05-13 18:34:33 +08:00
xushiwei
947e5591ea py llgo_autogen 2024-05-13 18:32:43 +08:00
xushiwei
521376e8e8 py 2024-05-13 18:29:00 +08:00
xushiwei
55c0adb23d _testpy/callpy fix 2024-05-13 18:25:05 +08:00
xushiwei
b20ad7047f _xtool: llpyg 2024-05-13 18:24:00 +08:00
xushiwei
fa3149c660 Update README.md 2024-05-13 01:27:02 +08:00
xushiwei
1463ed4835 Merge pull request #155 from xushiwei/q
retract v0.8.0
2024-05-13 01:01:25 +08:00
xushiwei
b959de18d5 retract v0.8.0 2024-05-13 01:00:54 +08:00
xushiwei
edac3f73c2 Merge pull request #154 from xushiwei/q
compileBlock bugfix: pyMod
2024-05-13 00:52:57 +08:00
xushiwei
388b19eed5 _testpy: sort by module name 2024-05-13 00:50:58 +08:00
xushiwei
a337136389 _testpy 2024-05-13 00:45:41 +08:00
xushiwei
31d5a8ac10 compileBlock bugfix: pyMod 2024-05-13 00:41:42 +08:00
xushiwei
46527f56ce Update README.md 2024-05-13 00:10:28 +08:00
xushiwei
a575c17eca Merge pull request #153 from xushiwei/q
README
2024-05-13 00:05:46 +08:00
xushiwei
a6ea3b1e6f README 2024-05-12 23:59:24 +08:00
xushiwei
4d2ad842a4 Merge pull request #152 from xushiwei/q
llgo/ssa: LoadPyModSyms; SetBlockEx AfterInit
2024-05-12 23:47:51 +08:00
xushiwei
ce0f5f3797 testpy: os.Getcwd 2024-05-12 23:45:56 +08:00
xushiwei
9e0d22ac90 x/sqlite/llgo_autogen.lla 2024-05-12 23:43:51 +08:00
xushiwei
ddc2c56115 gentests 2024-05-12 23:42:16 +08:00
xushiwei
acfbe6902a FuncDecl bugfix: even in C, we need to add ctx for method 2024-05-12 23:37:12 +08:00
xushiwei
f7dfab481b vkPyFunc => vkPyFuncRef 2024-05-12 23:08:44 +08:00
xushiwei
23692430d5 llgo/ssa: SetBlockEx AfterInit 2024-05-12 22:51:25 +08:00
xushiwei
03fe594339 compileBlock: use LoadPyModSyms 2024-05-12 20:03:27 +08:00
xushiwei
45babef689 compileBlock refactor 2024-05-12 18:42:45 +08:00
xushiwei
9ac0450255 llgo/ssa: LoadPyModSyms 2024-05-12 18:27:23 +08:00
xushiwei
b1d55f657d Merge pull request #151 from xushiwei/q
llgo/ssa: StringData/StringLen; cl: TestPython; build: PkgLinkExtern
2024-05-12 15:59:58 +08:00
xushiwei
aac5e7b3cd TestFromTestdata: print 2024-05-12 15:56:05 +08:00
xushiwei
791634c377 conflict fix 2024-05-12 15:52:29 +08:00
xushiwei
090149eab6 llgo/ssa: StringData/StringLen 2024-05-12 15:42:50 +08:00
xushiwei
acecbf587d cl: TestPython; build: PkgLinkExtern 2024-05-12 13:05:15 +08:00
xushiwei
4ef46971d0 Merge pull request #150 from xushiwei/q
TestFromTestpymath; llgo/ssa: NewPyFunc add param doInit
2024-05-12 12:18:09 +08:00
xushiwei
2e3cc49782 llgo/ssa: NewPyFunc add param doInit 2024-05-12 12:14:26 +08:00
xushiwei
8a0189b079 TestFromTestpymath 2024-05-12 11:51:46 +08:00
xushiwei
0edd7f6df0 Merge pull request #149 from xushiwei/q
PyInit
2024-05-12 11:28:04 +08:00
xushiwei
0b058bc2e8 test NewPyModVar 2024-05-12 11:26:09 +08:00
xushiwei
f9ef9cab81 TestSetBlockEx 2024-05-12 11:22:55 +08:00
xushiwei
fbb2150d88 TestFromTestpy 2024-05-12 11:13:04 +08:00
xushiwei
0912f1f509 PyInit 2024-05-12 11:11:19 +08:00
xushiwei
64c13fa9ae llgo/ssa: NewPyFunc fix 2024-05-12 00:24:56 +08:00
xushiwei
2a5f9d9641 Merge pull request #148 from xushiwei/q
_pydemo: callpy; PyFunction
2024-05-11 23:55:32 +08:00
xushiwei
6c32fe87e6 TestSetPython, TestPyFunc 2024-05-11 23:53:08 +08:00
xushiwei
09e9cc99d3 Merge pull request #147 from visualfc/typenamed
fix types named recursive
2024-05-11 23:42:06 +08:00
xushiwei
94a7ee024a llgo/ssa: pyCall; demo: _pydemo/callpy 2024-05-11 23:38:21 +08:00
xushiwei
a2d7a8c978 llgo/ssa: PyFunction; NewPyFunc 2024-05-11 21:55:50 +08:00
xushiwei
15499ddc14 cl: _testpy/math 2024-05-11 15:12:42 +08:00
xushiwei
97cb312386 llgo/ssa: b.NewPyModVar, b.ImportPyMod, PyObjectPtr, PyObjectPtrPtr 2024-05-11 15:07:50 +08:00
visualfc
92827a1f04 fix types named recursive 2024-05-11 13:34:08 +08:00
xushiwei
00222c7808 compileBlock: support pyModule init 2024-05-11 11:33:35 +08:00
xushiwei
427d87be68 cl: initPyModule 2024-05-11 10:07:46 +08:00
xushiwei
2560a333b6 FloatAsDouble => Float64 2024-05-11 06:55:57 +08:00
xushiwei
c6b76db789 Merge pull request #146 from xushiwei/q
LLGoPackage: PkgPyModule
2024-05-11 06:47:25 +08:00
xushiwei
1414853fce LLGoPackage: PkgPyModule 2024-05-11 06:44:45 +08:00
xushiwei
cbe384a3be Merge pull request #145 from xushiwei/q
pyimport & deomo: callpy (todo)
2024-05-11 06:25:35 +08:00
xushiwei
cca46573ea pyimport & deomo: callpy (todo) 2024-05-11 06:23:05 +08:00
xushiwei
2589c23998 Merge pull request #144 from xushiwei/q
nmindex: query auto add _ prefix
2024-05-11 05:45:26 +08:00
xushiwei
29830865d9 nmindex: query auto add _ prefix 2024-05-11 05:43:27 +08:00
xushiwei
35dbc7b0b5 Merge pull request #143 from xushiwei/q
mv x/<tool> => xtool/<tool>
2024-05-11 05:29:38 +08:00
xushiwei
cd266213ce mv x/<tool> => xtool/<tool> 2024-05-11 05:27:38 +08:00
xushiwei
875eadeb19 Merge pull request #142 from xushiwei/q
py/README
2024-05-11 05:18:41 +08:00
xushiwei
67896c63a7 py/README 2024-05-11 05:18:17 +08:00
xushiwei
c643f734e9 Merge pull request #141 from xushiwei/q
move python demos to _pydemo
2024-05-11 05:05:07 +08:00
xushiwei
31d91f5e87 move python demos to _pydemo 2024-05-11 05:04:02 +08:00
xushiwei
2a92f1bc55 Merge pull request #140 from xushiwei/q
py demo: hellpy, clpy, callpy
2024-05-11 04:31:40 +08:00
xushiwei
d9db5528f5 py demo: hellpy, clpy, callpy 2024-05-11 04:26:41 +08:00
xushiwei
22a4ffb78b Merge pull request #139 from visualfc/iface
typeAssert: bool float string
2024-05-11 02:49:31 +08:00
visualfc
1fb37c37fe binop: token.AND_NOT 2024-05-10 21:34:54 +08:00
visualfc
aae663e5e5 binop: bool eql/neq 2024-05-10 21:06:19 +08:00
visualfc
e985eda857 typeAssert: bool float string 2024-05-10 13:46:39 +08:00
140 changed files with 18059 additions and 714 deletions

2
.gitignore vendored
View File

@@ -13,11 +13,13 @@ llgo_autogen.ll
stories*.bin
.DS_Store
err.log
numpy.txt
_go/
_runtime/
_tinygo/
build.dir/
.vscode/
# Test binary, built with `go test -c`
*.test

3
.gitmodules vendored
View File

@@ -1,6 +1,3 @@
[submodule "x/llama2/llama2.c"]
path = x/llama2/llama2.c
url = https://github.com/karpathy/llama2.c.git
[submodule "x/sqlite/sqlite"]
path = x/sqlite/sqlite
url = https://github.com/sqlite/sqlite.git

199
README.md
View File

@@ -8,7 +8,185 @@ llgo - A Go compiler based on LLVM
[![GoDoc](https://pkg.go.dev/badge/github.com/goplus/llgo.svg)](https://pkg.go.dev/github.com/goplus/llgo)
[![Language](https://img.shields.io/badge/language-Go+-blue.svg)](https://github.com/goplus/gop)
This is a Go compiler based on LLVM in order to better integrate Go with the C ecosystem. It's a subproject of [the Go+ project](https://github.com/goplus/gop).
LLGo is a Go compiler based on LLVM in order to better integrate Go with the C ecosystem including Python. It's a subproject of [the Go+ project](https://github.com/goplus/gop).
## C standard libary support
```go
package main
import "github.com/goplus/llgo/c"
func main() {
c.Printf(c.Str("Hello world\n"))
}
```
This is a simple example of calling the C `printf` function to print `Hello world`. Here, `c.Str` is not a function for converting a Go string to a C string, but a built-in instruction supported by `llgo` for generating a C string constant.
The `_demo` directory contains some C standard libary related demos (it start with `_` to prevent the `go` command from compiling it):
* [hello](_demo/hello/hello.go): call C `printf` to print `Hello world`
* [concat](_demo/concat/concat.go): call C `fprintf` with `stderr`
* [qsort](_demo/qsort/qsort.go): call C function with a callback (eg. `qsort`)
To run these demos (If you haven't installed `llgo` yet, please refer to [How to install](#how-to-install)):
```sh
export LLGOROOT=`pwd`
cd <demo-directory> # eg. cd _demo/genints
llgo run .
```
See [github.com/goplus/llgo/c](https://pkg.go.dev/github.com/goplus/llgo/c) for more detials.
## Python support
You can import a Python library in LLGo!
And you can import any Python library into `llgo` through a program called `llpyg`. The currently imported libraries include:
* [sys](https://pkg.go.dev/github.com/goplus/llgo/py/sys)
* [os](https://pkg.go.dev/github.com/goplus/llgo/py/os)
* [math](https://pkg.go.dev/github.com/goplus/llgo/py/math)
* [json](https://pkg.go.dev/github.com/goplus/llgo/py/json)
* [inspect](https://pkg.go.dev/github.com/goplus/llgo/py/inspect)
* [statistics](https://pkg.go.dev/github.com/goplus/llgo/py/statistics)
* [numpy](https://pkg.go.dev/github.com/goplus/llgo/py/numpy)
Here is an example using the Python `math` library:
```go
package main
import (
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/py"
"github.com/goplus/llgo/py/math"
)
func main() {
x := math.Sqrt(py.Float(2))
c.Printf(c.Str("sqrt(2) = %f\n"), x.Float64())
}
```
Here, We call `py.Float(2)` to create a Python number 2, and pass it to Pythons `math.sqrt` to get `x`. Then use `x.Float64()` to convert x to Go's `float64` type, and print the value through the C `printf` function.
Let's look at a slightly more complex example. For example, we use `numpy` to calculate:
```go
package main
import (
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/py"
"github.com/goplus/llgo/py/numpy"
)
func main() {
a := py.List(
py.List(1.0, 2.0, 3.0),
py.List(4.0, 5.0, 6.0),
py.List(7.0, 8.0, 9.0),
)
b := py.List(
py.List(9.0, 8.0, 7.0),
py.List(6.0, 5.0, 4.0),
py.List(3.0, 2.0, 1.0),
)
x := numpy.Add(a, b)
c.Printf(c.Str("a+b = %s\n"), x.Str().CStr())
}
```
Here we define two 3x3 matrices a and b, add them to get x, and then print the result.
The `_pydemo` directory contains some python related demos:
* [callpy](_pydemo/callpy/callpy.go): call Python standard library function `math.sqrt`
* [pi](_pydemo/pi/pi.go): print python constants `math.pi`
* [statistics](_pydemo/statistics/statistics.go): define a python list and call `statistics.mean` to get the mean
* [matrix](_pydemo/matrix/matrix.go): a basic `numpy` demo
To run these demos, you need to set the `LLGO_LIB_PYTHON` environment variable first.
If Python is in the search path for `clang` linking, then `LLGO_LIB_PYTHON` only needs to be set to the name of the Python library. For example:
```sh
export LLGO_LIB_PYTHON=python3.12
```
You can also specify the path to tell `llgo` where the Python library is located:
```sh
export LLGO_LIB_PYTHON=/foo/bar/python3.12
```
For example, `/opt/homebrew/Frameworks/Python.framework/Versions/3.12/libpython3.12.dylib` is a typical python library location under macOS. So we should set it like this:
```sh
export LLGO_LIB_PYTHON=/opt/homebrew/Frameworks/Python.framework/Versions/3.12/python3.12
```
Note that the file name must be written in a platform-independent format, using `python3.12` instead of `libpython3.12.dylib`.
Then you can run the demos:
```sh
export LLGOROOT=`pwd`
cd <demo-directory> # eg. cd _pydemo/callpy
llgo run .
```
See [github.com/goplus/llgo/py](https://pkg.go.dev/github.com/goplus/llgo/py) for more detials.
## Other frequently used libraries
LLGo can easily import any libraries from the C ecosystem. Currently, this import process is still manual, but in the future, it will be automated similar to Python library imports.
The currently imported libraries include:
* [llama2.c](https://pkg.go.dev/github.com/goplus/llgo/x/llama2)
* [cjson](https://pkg.go.dev/github.com/goplus/llgo/x/cjson)
* [sqlite](https://pkg.go.dev/github.com/goplus/llgo/x/sqlite)
Here are some examples related to them:
* [llama2-c](_demo/llama2-c): inference Llama 2 (It's the first llgo AI example)
* [mkjson](x/cjson/_demo/mkjson/mkjson.go): create a json object and print it
* [sqlite](x/sqlite/_demo/sqlitedemo/demo.go): a basic sqlite demo
## Go syntax support
The priority of `llgo` feature iteration is:
* Popular C/Python libraries
* Full Go syntax
* Go standard libraries
* Popular Go packages
Common Go syntax is already supported. Except for the following, which needs to be improved:
* interface (Limited support)
* map (Very limited support)
* panic (Limited support)
* recover (Not supported yet)
* defer (Not supported yet)
* gc (Not supported yet)
* chan (Not supported yet)
* goroutine (Not supported yet)
* generics (Not supported yet)
Here are some examples related to Go syntax:
* [concat](_demo/concat/concat.go): define a variadic function
* [genints](_demo/genints/genints.go): various forms of closure usage (including C function, recv.method and anonymous function)
## How to install
@@ -35,22 +213,3 @@ go install -v ./...
### on Windows
TODO
## Demo
The `_demo` directory contains our demos (it start with `_` to prevent the `go` command from compiling it):
* [hello](_demo/hello/hello.go): call C printf to print `Hello world`
* [concat](_demo/concat/concat.go): call C fprintf with stderr, and Go variadic function
* [qsort](_demo/qsort/qsort.go): call C function with a callback (eg. qsort)
* [genints](_demo/genints/genints.go): various forms of closure usage (including C function, recv.method and anonymous function)
* [llama2-c](_demo/llama2-c): inference Llama 2 (It's the first llgo AI example)
* [hellopy](https://github.com/goplus/cpython/blob/main/_demo/hellopy/hello.go): link Python to Go and say `Hello world`
### How to run demos
```sh
cd <demo-directory> # eg. cd _demo/genints
llgo run .
```

12
_pydemo/callpy/callpy.go Normal file
View File

@@ -0,0 +1,12 @@
package main
import (
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/py"
"github.com/goplus/llgo/py/math"
)
func main() {
x := math.Sqrt(py.Float(2))
c.Printf(c.Str("sqrt(2) = %f\n"), x.Float64())
}

22
_pydemo/matrix/matrix.go Normal file
View File

@@ -0,0 +1,22 @@
package main
import (
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/py"
"github.com/goplus/llgo/py/numpy"
)
func main() {
a := py.List(
py.List(1.0, 2.0, 3.0),
py.List(4.0, 5.0, 6.0),
py.List(7.0, 8.0, 9.0),
)
b := py.List(
py.List(9.0, 8.0, 7.0),
py.List(6.0, 5.0, 4.0),
py.List(3.0, 2.0, 1.0),
)
x := numpy.Add(a, b)
c.Printf(c.Str("a+b = %s\n"), x.Str().CStr())
}

10
_pydemo/pi/pi.go Normal file
View File

@@ -0,0 +1,10 @@
package main
import (
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/py/math"
)
func main() {
c.Printf(c.Str("pi = %f\n"), math.Pi.Float64())
}

View File

@@ -0,0 +1,13 @@
package main
import (
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/py"
"github.com/goplus/llgo/py/statistics"
)
func main() {
list := py.List(1.0, 2.0, 3.0, 4.0, 4.0)
mean := statistics.Mean(list)
c.Printf(c.Str("mean(1, 2, 3, 4, 4) = %f\n"), mean.Float64())
}

18
c/c.go
View File

@@ -25,12 +25,16 @@ const (
)
type (
Char = int8
Int = C.int
Uint = C.uint
Float = float32
Pointer = unsafe.Pointer
FilePtr = unsafe.Pointer
Char = int8
Int = C.int
Uint = C.uint
Long = int32
Ulong = uint32
LongLong = int64
UlongLong = uint64
Float = float32
Pointer = unsafe.Pointer
FilePtr = unsafe.Pointer
)
type integer interface {
@@ -66,7 +70,7 @@ func Memset(s Pointer, c Int, n uintptr) Pointer
// -----------------------------------------------------------------------------
//go:linkname GoStringData github.com/goplus/llgo/internal/runtime.StringData
//go:linkname GoStringData llgo.stringData
func GoStringData(string) *Char
// -----------------------------------------------------------------------------

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package main
import (
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/py"
"github.com/goplus/llgo/py/inspect"
"github.com/goplus/llgo/x/cjson"
)
func main() {
if c.Argc < 2 {
c.Fprintf(c.Stderr, c.Str("Usage: pydump <pythonLibPath>\n"))
return
}
pyLib := c.Index(c.Argv, 1)
py.Initialize()
root := cjson.Object()
root.SetItem(c.Str("name"), cjson.String(pyLib))
items := cjson.Array()
mod := py.ImportModule(pyLib)
keys := mod.ModuleGetDict().DictKeys()
for i, n := uintptr(0), keys.ListLen(); i < n; i++ {
key := keys.ListItem(i)
val := mod.GetAttr(key)
doc := val.GetAttrString(c.Str("__doc__"))
sym := cjson.Object()
sym.SetItem(c.Str("type"), cjson.String(val.Type().TypeName().CStr()))
sym.SetItem(c.Str("name"), cjson.String(key.CStr()))
if doc != nil {
sym.SetItem(c.Str("doc"), cjson.String(doc.CStr()))
}
if val.Callable() != 0 {
sig := inspect.Signature(val)
sym.SetItem(c.Str("sig"), cjson.String(sig.Str().CStr()))
}
items.AddItem(sym)
}
root.SetItem(c.Str("items"), items)
c.Printf(c.Str("%s\n"), root.CStr())
}

View File

@@ -22,7 +22,7 @@ import (
"log"
"os"
"github.com/goplus/llgo/x/ar"
"github.com/goplus/llgo/xtool/ar"
)
func main() {

View File

@@ -22,7 +22,7 @@ import (
"fmt"
"os"
"github.com/goplus/llgo/x/clang/parser"
"github.com/goplus/llgo/xtool/clang/parser"
)
var (

View File

@@ -20,7 +20,7 @@ import (
"fmt"
"os"
"github.com/goplus/llgo/x/clang/preprocessor"
"github.com/goplus/llgo/xtool/clang/preprocessor"
)
func usage() {

View File

@@ -33,6 +33,7 @@ func main() {
llgenDir(dir + "/cl/_testlibc")
llgenDir(dir + "/cl/_testrt")
llgenDir(dir+"/cl/_testpy", "")
llgenDir(dir+"/cl/_testdata", "")
}

200
chore/llpyg/llpyg.go Normal file
View File

@@ -0,0 +1,200 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package main
import (
"bytes"
"encoding/json"
"fmt"
"go/ast"
"go/token"
"go/types"
"log"
"os"
"os/exec"
"strings"
"github.com/goplus/gogen"
"github.com/goplus/llgo/ssa"
)
type symbol struct {
Name string `json:"name"`
Type string `json:"type"`
Doc string `json:"doc"`
Sig string `json:"sig"`
}
type module struct {
Name string `json:"name"`
Items []*symbol `json:"items"`
}
func main() {
if len(os.Args) < 2 {
fmt.Fprintln(os.Stderr, "Usage: llpyg <pythonLibPath>")
return
}
pyLib := os.Args[1]
var out bytes.Buffer
pydump := exec.Command("pydump", pyLib)
pydump.Stdout = &out
pydump.Run()
var mod module
json.Unmarshal(out.Bytes(), &mod)
modName := mod.Name
if modName == "" {
log.Printf("import module %s failed\n", pyLib)
os.Exit(1)
}
pkg := gogen.NewPackage("", modName, nil)
pkg.Import("unsafe").MarkForceUsed(pkg) // import _ "unsafe"
py := pkg.Import("github.com/goplus/llgo/py") // import "github.com/goplus/llgo/py"
f := func(cb *gogen.CodeBuilder) int {
cb.Val("py." + modName)
return 1
}
defs := pkg.NewConstDefs(pkg.Types.Scope())
defs.New(f, 0, 0, nil, "LLGoPackage")
obj := py.Ref("Object").(*types.TypeName).Type().(*types.Named)
objPtr := types.NewPointer(obj)
ret := types.NewTuple(pkg.NewParam(0, "", objPtr))
ctx := &context{pkg, obj, objPtr, ret, py}
for _, sym := range mod.Items {
switch sym.Type {
case "builtin_function_or_method", "function", "ufunc", "method-wrapper":
ctx.genFunc(pkg, sym)
case "str", "float", "bool", "type", "dict", "tuple", "list", "object",
"module", "int", "set", "frozenset", "flags", "bool_": // skip
default:
t := sym.Type
if len(t) > 0 && (t[0] >= 'a' && t[0] <= 'z') && !strings.HasSuffix(t, "_info") {
log.Panicln("unsupport type:", sym.Type)
}
}
}
pkg.WriteTo(os.Stdout)
}
type context struct {
pkg *gogen.Package
obj *types.Named
objPtr *types.Pointer
ret *types.Tuple
py gogen.PkgRef
}
func (ctx *context) genFunc(pkg *gogen.Package, sym *symbol) {
name, symSig := sym.Name, sym.Sig
if len(name) == 0 || name[0] == '_' {
return
}
params, variadic, skip := ctx.genParams(pkg, symSig)
if skip {
// TODO(xsw): don't skip any func
log.Println("skip func:", name, symSig)
return
}
name = genName(name, -1)
sig := types.NewSignatureType(nil, nil, nil, params, ctx.ret, variadic)
fn := pkg.NewFuncDecl(token.NoPos, name, sig)
list := ctx.genDoc(sym.Doc)
list = append(list, emptyCommentLine)
list = append(list, ctx.genLinkname(name, sym))
fn.SetComments(pkg, &ast.CommentGroup{List: list})
// fn.BodyStart(pkg).End()
}
func (ctx *context) genParams(pkg *gogen.Package, sig string) (*types.Tuple, bool, bool) {
if sig == "<NULL>" {
return nil, false, true
}
sig = strings.TrimSuffix(strings.TrimPrefix(sig, "("), ")")
if sig == "" { // empty params
return nil, false, false
}
parts := strings.Split(sig, ",")
n := len(parts)
objPtr := ctx.objPtr
list := make([]*types.Var, 0, n)
for i := 0; i < n; i++ {
part := strings.TrimSpace(parts[i])
if part == "/" {
continue
}
if part == "*" {
break
}
if strings.HasPrefix(part, "*") {
if part[1] != '*' {
list = append(list, ssa.VArg())
return types.NewTuple(list...), true, false
}
return types.NewTuple(list...), false, false
}
pos := strings.IndexByte(part, '=')
if pos >= 0 {
if strings.HasPrefix(part[pos+1:], "<") { // skip complex default value
return nil, false, true
}
part = part[:pos]
}
list = append(list, pkg.NewParam(0, genName(part, 0), objPtr))
}
return types.NewTuple(list...), false, false
}
func genName(name string, idxDontTitle int) string {
parts := strings.Split(name, "_")
for i, part := range parts {
if i != idxDontTitle && part != "" {
if c := part[0]; c >= 'a' && c <= 'z' {
part = string(c+'A'-'a') + part[1:]
}
parts[i] = part
}
}
name = strings.Join(parts, "")
switch name {
case "default", "func", "":
name += "_"
}
return name
}
func (ctx *context) genLinkname(name string, sym *symbol) *ast.Comment {
return &ast.Comment{Text: "//go:linkname " + name + " py." + sym.Name}
}
func (ctx *context) genDoc(doc string) []*ast.Comment {
lines := strings.Split(doc, "\n")
list := make([]*ast.Comment, len(lines), len(lines)+2)
for i, line := range lines {
list[i] = &ast.Comment{Text: "// " + line}
}
return list
}
var (
emptyCommentLine = &ast.Comment{Text: "//"}
)

View File

@@ -21,7 +21,7 @@ import (
"log"
"os"
"github.com/goplus/llgo/x/env/llvm"
"github.com/goplus/llgo/xtool/env/llvm"
)
func main() {

View File

@@ -20,8 +20,8 @@ import (
"fmt"
"os"
"github.com/goplus/llgo/x/env/llvm"
"github.com/goplus/llgo/x/nm"
"github.com/goplus/llgo/xtool/env/llvm"
"github.com/goplus/llgo/xtool/nm"
)
func main() {
@@ -73,6 +73,11 @@ func makeIndex() {
}
func query(q string) {
if len(q) > 0 {
if c := q[0]; c != '*' && c != '_' {
q = "_" + q
}
}
files, err := nm.Query(indexDir(), q)
check(err)
for _, f := range files {

View File

@@ -13,6 +13,14 @@ func gwrite(b []byte) {
c.Printf(c.Str("%s"), b)
}
func printbool(v bool) {
if v {
printstring("true")
} else {
printstring("false")
}
}
func printfloat(v float64) {
switch {
case v != v:
@@ -177,14 +185,37 @@ func main() {
printnl()
prinfsub(100.1)
printnl()
printnum(float32(1e9))
printany(float32(1e9))
printnl()
printnum(float64(2e9))
printany(float64(2e9))
printnl()
var b bool = true
if b == true && b != false {
println("check bool", b)
}
n1 := 0b1001
n2 := 0b0011
println("check &^", n1&^n2 == 0b1000, n2&^n1 == 0b0010)
println(true, false, 'a', 'A', rune('中'),
int8(1), int16(2), int32(3), int64(4), 5,
uint8(1), uint16(2), uint32(3), uint64(4), uintptr(5),
"llgo")
}
func println(args ...any) {
for i, v := range args {
if i != 0 {
printstring(" ")
}
printany(v)
}
printnl()
}
func printnum(v any) {
func printany(v any) {
switch v := v.(type) {
case bool:
printbool(v)
case int:
printint(int64(v))
case int8:
@@ -211,6 +242,8 @@ func printnum(v any) {
printfloat(float64(v))
case float64:
printfloat(float64(v))
case string:
printstring(v)
}
}

View File

@@ -13,13 +13,19 @@ source_filename = "main"
@__llgo_argc = global ptr null
@__llgo_argv = global ptr null
@1 = private unnamed_addr constant [5 x i8] c"llgo\00", align 1
@2 = private unnamed_addr constant [4 x i8] c"NaN\00", align 1
@3 = private unnamed_addr constant [5 x i8] c"+Inf\00", align 1
@4 = private unnamed_addr constant [5 x i8] c"-Inf\00", align 1
@5 = private unnamed_addr constant [17 x i8] c"0123456789abcdef\00", align 1
@6 = private unnamed_addr constant [2 x i8] c"-\00", align 1
@7 = private unnamed_addr constant [2 x i8] c"\0A\00", align 1
@8 = private unnamed_addr constant [2 x i8] c" \00", align 1
@2 = private unnamed_addr constant [11 x i8] c"check bool\00", align 1
@3 = private unnamed_addr constant [9 x i8] c"check &^\00", align 1
@4 = private unnamed_addr constant [5 x i8] c"llgo\00", align 1
@5 = private unnamed_addr constant [5 x i8] c"true\00", align 1
@6 = private unnamed_addr constant [6 x i8] c"false\00", align 1
@7 = private unnamed_addr constant [4 x i8] c"NaN\00", align 1
@8 = private unnamed_addr constant [5 x i8] c"+Inf\00", align 1
@9 = private unnamed_addr constant [5 x i8] c"-Inf\00", align 1
@10 = private unnamed_addr constant [17 x i8] c"0123456789abcdef\00", align 1
@11 = private unnamed_addr constant [2 x i8] c"-\00", align 1
@12 = private unnamed_addr constant [2 x i8] c" \00", align 1
@13 = private unnamed_addr constant [2 x i8] c"\0A\00", align 1
@14 = private unnamed_addr constant [2 x i8] c" \00", align 1
define %"github.com/goplus/llgo/internal/runtime.Slice" @main.bytes(%"github.com/goplus/llgo/internal/runtime.String" %0) {
_llgo_0:
@@ -45,7 +51,7 @@ _llgo_0:
define void @main.gwrite(%"github.com/goplus/llgo/internal/runtime.Slice" %0) {
_llgo_0:
%1 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %0)
%1 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 1
%2 = icmp eq i64 %1, 0
br i1 %2, label %_llgo_1, label %_llgo_2
@@ -94,13 +100,115 @@ _llgo_0:
call void @main.printnl()
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 13)
%4 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %3, i64 1315859240)
call void @main.printnum(%"github.com/goplus/llgo/internal/runtime.iface" %4)
call void @main.printany(%"github.com/goplus/llgo/internal/runtime.iface" %4)
call void @main.printnl()
%5 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 14)
%6 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %5, i64 4746175415993761792)
call void @main.printnum(%"github.com/goplus/llgo/internal/runtime.iface" %6)
call void @main.printany(%"github.com/goplus/llgo/internal/runtime.iface" %6)
call void @main.printnl()
br i1 true, label %_llgo_3, label %_llgo_2
_llgo_1: ; preds = %_llgo_3
%7 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
%8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %7, i64 0
%9 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @2, i64 10)
%10 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %9)
store %"github.com/goplus/llgo/internal/runtime.iface" %10, ptr %8, align 8
%11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %7, i64 1
%12 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 1)
%13 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %12, i64 -1)
store %"github.com/goplus/llgo/internal/runtime.iface" %13, ptr %11, align 8
%14 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %7, i64 16, i64 2, i64 0, i64 2, i64 2)
call void @main.println(%"github.com/goplus/llgo/internal/runtime.Slice" %14)
br label %_llgo_2
_llgo_2: ; preds = %_llgo_3, %_llgo_1, %_llgo_0
%15 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 48)
%16 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %15, i64 0
%17 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @3, i64 8)
%18 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %17)
store %"github.com/goplus/llgo/internal/runtime.iface" %18, ptr %16, align 8
%19 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %15, i64 1
%20 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 1)
%21 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %20, i64 -1)
store %"github.com/goplus/llgo/internal/runtime.iface" %21, ptr %19, align 8
%22 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %15, i64 2
%23 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 1)
%24 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %23, i64 -1)
store %"github.com/goplus/llgo/internal/runtime.iface" %24, ptr %22, align 8
%25 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %15, i64 16, i64 3, i64 0, i64 3, i64 3)
call void @main.println(%"github.com/goplus/llgo/internal/runtime.Slice" %25)
%26 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 256)
%27 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 0
%28 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 1)
%29 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %28, i64 -1)
store %"github.com/goplus/llgo/internal/runtime.iface" %29, ptr %27, align 8
%30 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 1
%31 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 1)
%32 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %31, i64 0)
store %"github.com/goplus/llgo/internal/runtime.iface" %32, ptr %30, align 8
%33 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 2
%34 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 5)
%35 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %34, i64 97)
store %"github.com/goplus/llgo/internal/runtime.iface" %35, ptr %33, align 8
%36 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 3
%37 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 5)
%38 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %37, i64 65)
store %"github.com/goplus/llgo/internal/runtime.iface" %38, ptr %36, align 8
%39 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 4
%40 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 5)
%41 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %40, i64 20013)
store %"github.com/goplus/llgo/internal/runtime.iface" %41, ptr %39, align 8
%42 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 5
%43 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 3)
%44 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %43, i64 1)
store %"github.com/goplus/llgo/internal/runtime.iface" %44, ptr %42, align 8
%45 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 6
%46 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 4)
%47 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %46, i64 2)
store %"github.com/goplus/llgo/internal/runtime.iface" %47, ptr %45, align 8
%48 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 7
%49 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 5)
%50 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %49, i64 3)
store %"github.com/goplus/llgo/internal/runtime.iface" %50, ptr %48, align 8
%51 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 8
%52 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 6)
%53 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %52, i64 4)
store %"github.com/goplus/llgo/internal/runtime.iface" %53, ptr %51, align 8
%54 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 9
%55 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2)
%56 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %55, i64 5)
store %"github.com/goplus/llgo/internal/runtime.iface" %56, ptr %54, align 8
%57 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 10
%58 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 8)
%59 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %58, i64 1)
store %"github.com/goplus/llgo/internal/runtime.iface" %59, ptr %57, align 8
%60 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 11
%61 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 9)
%62 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %61, i64 2)
store %"github.com/goplus/llgo/internal/runtime.iface" %62, ptr %60, align 8
%63 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 12
%64 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 10)
%65 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %64, i64 3)
store %"github.com/goplus/llgo/internal/runtime.iface" %65, ptr %63, align 8
%66 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 13
%67 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 11)
%68 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %67, i64 4)
store %"github.com/goplus/llgo/internal/runtime.iface" %68, ptr %66, align 8
%69 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 14
%70 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 12)
%71 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %70, i64 5)
store %"github.com/goplus/llgo/internal/runtime.iface" %71, ptr %69, align 8
%72 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 15
%73 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @4, i64 4)
%74 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %73)
store %"github.com/goplus/llgo/internal/runtime.iface" %74, ptr %72, align 8
%75 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %26, i64 16, i64 16, i64 0, i64 16, i64 16)
call void @main.println(%"github.com/goplus/llgo/internal/runtime.Slice" %75)
ret void
_llgo_3: ; preds = %_llgo_0
br i1 true, label %_llgo_1, label %_llgo_2
}
define void @main.prinfsub(double %0) {
@@ -117,18 +225,223 @@ _llgo_0:
ret void
}
define void @main.printany(%"github.com/goplus/llgo/internal/runtime.iface" %0) {
_llgo_0:
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 1)
%2 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %1)
%3 = extractvalue { i64, i1 } %2, 0
%4 = trunc i64 %3 to i1
%5 = extractvalue { i64, i1 } %2, 1
br i1 %5, label %_llgo_2, label %_llgo_3
_llgo_1: ; preds = %_llgo_30, %_llgo_29, %_llgo_28, %_llgo_26, %_llgo_24, %_llgo_22, %_llgo_20, %_llgo_18, %_llgo_16, %_llgo_14, %_llgo_12, %_llgo_10, %_llgo_8, %_llgo_6, %_llgo_4, %_llgo_2
ret void
_llgo_2: ; preds = %_llgo_0
call void @main.printbool(i1 %4)
br label %_llgo_1
_llgo_3: ; preds = %_llgo_0
%6 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2)
%7 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %6)
%8 = extractvalue { i64, i1 } %7, 0
%9 = extractvalue { i64, i1 } %7, 1
br i1 %9, label %_llgo_4, label %_llgo_5
_llgo_4: ; preds = %_llgo_3
call void @main.printint(i64 %8)
br label %_llgo_1
_llgo_5: ; preds = %_llgo_3
%10 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 3)
%11 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %10)
%12 = extractvalue { i64, i1 } %11, 0
%13 = trunc i64 %12 to i8
%14 = extractvalue { i64, i1 } %11, 1
br i1 %14, label %_llgo_6, label %_llgo_7
_llgo_6: ; preds = %_llgo_5
%15 = sext i8 %13 to i64
call void @main.printint(i64 %15)
br label %_llgo_1
_llgo_7: ; preds = %_llgo_5
%16 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 4)
%17 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %16)
%18 = extractvalue { i64, i1 } %17, 0
%19 = trunc i64 %18 to i16
%20 = extractvalue { i64, i1 } %17, 1
br i1 %20, label %_llgo_8, label %_llgo_9
_llgo_8: ; preds = %_llgo_7
%21 = sext i16 %19 to i64
call void @main.printint(i64 %21)
br label %_llgo_1
_llgo_9: ; preds = %_llgo_7
%22 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 5)
%23 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %22)
%24 = extractvalue { i64, i1 } %23, 0
%25 = trunc i64 %24 to i32
%26 = extractvalue { i64, i1 } %23, 1
br i1 %26, label %_llgo_10, label %_llgo_11
_llgo_10: ; preds = %_llgo_9
%27 = sext i32 %25 to i64
call void @main.printint(i64 %27)
br label %_llgo_1
_llgo_11: ; preds = %_llgo_9
%28 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 6)
%29 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %28)
%30 = extractvalue { i64, i1 } %29, 0
%31 = extractvalue { i64, i1 } %29, 1
br i1 %31, label %_llgo_12, label %_llgo_13
_llgo_12: ; preds = %_llgo_11
call void @main.printint(i64 %30)
br label %_llgo_1
_llgo_13: ; preds = %_llgo_11
%32 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 7)
%33 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %32)
%34 = extractvalue { i64, i1 } %33, 0
%35 = extractvalue { i64, i1 } %33, 1
br i1 %35, label %_llgo_14, label %_llgo_15
_llgo_14: ; preds = %_llgo_13
call void @main.printuint(i64 %34)
br label %_llgo_1
_llgo_15: ; preds = %_llgo_13
%36 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 8)
%37 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %36)
%38 = extractvalue { i64, i1 } %37, 0
%39 = trunc i64 %38 to i8
%40 = extractvalue { i64, i1 } %37, 1
br i1 %40, label %_llgo_16, label %_llgo_17
_llgo_16: ; preds = %_llgo_15
%41 = sext i8 %39 to i64
call void @main.printuint(i64 %41)
br label %_llgo_1
_llgo_17: ; preds = %_llgo_15
%42 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 9)
%43 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %42)
%44 = extractvalue { i64, i1 } %43, 0
%45 = trunc i64 %44 to i16
%46 = extractvalue { i64, i1 } %43, 1
br i1 %46, label %_llgo_18, label %_llgo_19
_llgo_18: ; preds = %_llgo_17
%47 = sext i16 %45 to i64
call void @main.printuint(i64 %47)
br label %_llgo_1
_llgo_19: ; preds = %_llgo_17
%48 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 10)
%49 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %48)
%50 = extractvalue { i64, i1 } %49, 0
%51 = trunc i64 %50 to i32
%52 = extractvalue { i64, i1 } %49, 1
br i1 %52, label %_llgo_20, label %_llgo_21
_llgo_20: ; preds = %_llgo_19
%53 = sext i32 %51 to i64
call void @main.printuint(i64 %53)
br label %_llgo_1
_llgo_21: ; preds = %_llgo_19
%54 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 11)
%55 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %54)
%56 = extractvalue { i64, i1 } %55, 0
%57 = extractvalue { i64, i1 } %55, 1
br i1 %57, label %_llgo_22, label %_llgo_23
_llgo_22: ; preds = %_llgo_21
call void @main.printuint(i64 %56)
br label %_llgo_1
_llgo_23: ; preds = %_llgo_21
%58 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 12)
%59 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %58)
%60 = extractvalue { i64, i1 } %59, 0
%61 = extractvalue { i64, i1 } %59, 1
br i1 %61, label %_llgo_24, label %_llgo_25
_llgo_24: ; preds = %_llgo_23
call void @main.printuint(i64 %60)
br label %_llgo_1
_llgo_25: ; preds = %_llgo_23
%62 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 13)
%63 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %62)
%64 = extractvalue { i64, i1 } %63, 0
%65 = trunc i64 %64 to i32
%66 = bitcast i32 %65 to float
%67 = extractvalue { i64, i1 } %63, 1
br i1 %67, label %_llgo_26, label %_llgo_27
_llgo_26: ; preds = %_llgo_25
%68 = fpext float %66 to double
call void @main.printfloat(double %68)
br label %_llgo_1
_llgo_27: ; preds = %_llgo_25
%69 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 14)
%70 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %69)
%71 = extractvalue { i64, i1 } %70, 0
%72 = bitcast i64 %71 to double
%73 = extractvalue { i64, i1 } %70, 1
br i1 %73, label %_llgo_28, label %_llgo_29
_llgo_28: ; preds = %_llgo_27
call void @main.printfloat(double %72)
br label %_llgo_1
_llgo_29: ; preds = %_llgo_27
%74 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 24)
%75 = call { %"github.com/goplus/llgo/internal/runtime.String", i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2String"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %74)
%76 = extractvalue { %"github.com/goplus/llgo/internal/runtime.String", i1 } %75, 0
%77 = extractvalue { %"github.com/goplus/llgo/internal/runtime.String", i1 } %75, 1
br i1 %77, label %_llgo_30, label %_llgo_1
_llgo_30: ; preds = %_llgo_29
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %76)
br label %_llgo_1
}
define void @main.printbool(i1 %0) {
_llgo_0:
br i1 %0, label %_llgo_1, label %_llgo_3
_llgo_1: ; preds = %_llgo_0
%1 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @5, i64 4)
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %1)
br label %_llgo_2
_llgo_2: ; preds = %_llgo_3, %_llgo_1
ret void
_llgo_3: ; preds = %_llgo_0
%2 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @6, i64 5)
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %2)
br label %_llgo_2
}
define void @main.printfloat(double %0) {
_llgo_0:
%1 = fcmp one double %0, %0
br i1 %1, label %_llgo_1, label %_llgo_3
_llgo_1: ; preds = %_llgo_0
%2 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @2, i64 3)
%2 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @7, i64 3)
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %2)
ret void
_llgo_2: ; preds = %_llgo_7
%3 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @3, i64 4)
%3 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @8, i64 4)
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %3)
ret void
@@ -138,7 +451,7 @@ _llgo_3: ; preds = %_llgo_0
br i1 %5, label %_llgo_6, label %_llgo_7
_llgo_4: ; preds = %_llgo_10
%6 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @4, i64 4)
%6 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @9, i64 4)
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %6)
ret void
@@ -310,8 +623,8 @@ _llgo_0:
_llgo_1: ; preds = %_llgo_3
%2 = urem i64 %14, 16
%3 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @5, i64 16)
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String" %3)
%3 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @10, i64 16)
%4 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %3, 0
%5 = getelementptr inbounds i8, ptr %4, i64 %2
%6 = load i8, ptr %5, align 1
%7 = getelementptr inbounds i8, ptr %1, i64 %15
@@ -354,7 +667,7 @@ _llgo_0:
br i1 %1, label %_llgo_1, label %_llgo_2
_llgo_1: ; preds = %_llgo_0
%2 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @6, i64 1)
%2 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @11, i64 1)
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %2)
%3 = sub i64 0, %0
br label %_llgo_2
@@ -365,165 +678,48 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main.println(%"github.com/goplus/llgo/internal/runtime.Slice" %0) {
_llgo_0:
%1 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 1
br label %_llgo_1
_llgo_1: ; preds = %_llgo_5, %_llgo_0
%2 = phi i64 [ -1, %_llgo_0 ], [ %3, %_llgo_5 ]
%3 = add i64 %2, 1
%4 = icmp slt i64 %3, %1
br i1 %4, label %_llgo_2, label %_llgo_3
_llgo_2: ; preds = %_llgo_1
%5 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 0
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %5, i64 %3
%7 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %6, align 8
%8 = icmp ne i64 %3, 0
br i1 %8, label %_llgo_4, label %_llgo_5
_llgo_3: ; preds = %_llgo_1
call void @main.printnl()
ret void
_llgo_4: ; preds = %_llgo_2
%9 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @12, i64 1)
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %9)
br label %_llgo_5
_llgo_5: ; preds = %_llgo_4, %_llgo_2
call void @main.printany(%"github.com/goplus/llgo/internal/runtime.iface" %7)
br label %_llgo_1
}
define void @main.printnl() {
_llgo_0:
%0 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @7, i64 1)
%0 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @13, i64 1)
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %0)
ret void
}
define void @main.printnum(%"github.com/goplus/llgo/internal/runtime.iface" %0) {
_llgo_0:
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2)
%2 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %1)
%3 = extractvalue { i64, i1 } %2, 0
%4 = extractvalue { i64, i1 } %2, 1
br i1 %4, label %_llgo_2, label %_llgo_3
_llgo_1: ; preds = %_llgo_26, %_llgo_25, %_llgo_24, %_llgo_22, %_llgo_20, %_llgo_18, %_llgo_16, %_llgo_14, %_llgo_12, %_llgo_10, %_llgo_8, %_llgo_6, %_llgo_4, %_llgo_2
ret void
_llgo_2: ; preds = %_llgo_0
call void @main.printint(i64 %3)
br label %_llgo_1
_llgo_3: ; preds = %_llgo_0
%5 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 3)
%6 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %5)
%7 = extractvalue { i64, i1 } %6, 0
%8 = extractvalue { i64, i1 } %6, 1
br i1 %8, label %_llgo_4, label %_llgo_5
_llgo_4: ; preds = %_llgo_3
call void @main.printint(i64 %7)
br label %_llgo_1
_llgo_5: ; preds = %_llgo_3
%9 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 4)
%10 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %9)
%11 = extractvalue { i64, i1 } %10, 0
%12 = extractvalue { i64, i1 } %10, 1
br i1 %12, label %_llgo_6, label %_llgo_7
_llgo_6: ; preds = %_llgo_5
call void @main.printint(i64 %11)
br label %_llgo_1
_llgo_7: ; preds = %_llgo_5
%13 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 5)
%14 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %13)
%15 = extractvalue { i64, i1 } %14, 0
%16 = extractvalue { i64, i1 } %14, 1
br i1 %16, label %_llgo_8, label %_llgo_9
_llgo_8: ; preds = %_llgo_7
call void @main.printint(i64 %15)
br label %_llgo_1
_llgo_9: ; preds = %_llgo_7
%17 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 6)
%18 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %17)
%19 = extractvalue { i64, i1 } %18, 0
%20 = extractvalue { i64, i1 } %18, 1
br i1 %20, label %_llgo_10, label %_llgo_11
_llgo_10: ; preds = %_llgo_9
call void @main.printint(i64 %19)
br label %_llgo_1
_llgo_11: ; preds = %_llgo_9
%21 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 7)
%22 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %21)
%23 = extractvalue { i64, i1 } %22, 0
%24 = extractvalue { i64, i1 } %22, 1
br i1 %24, label %_llgo_12, label %_llgo_13
_llgo_12: ; preds = %_llgo_11
call void @main.printuint(i64 %23)
br label %_llgo_1
_llgo_13: ; preds = %_llgo_11
%25 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 8)
%26 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %25)
%27 = extractvalue { i64, i1 } %26, 0
%28 = extractvalue { i64, i1 } %26, 1
br i1 %28, label %_llgo_14, label %_llgo_15
_llgo_14: ; preds = %_llgo_13
call void @main.printuint(i64 %27)
br label %_llgo_1
_llgo_15: ; preds = %_llgo_13
%29 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 9)
%30 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %29)
%31 = extractvalue { i64, i1 } %30, 0
%32 = extractvalue { i64, i1 } %30, 1
br i1 %32, label %_llgo_16, label %_llgo_17
_llgo_16: ; preds = %_llgo_15
call void @main.printuint(i64 %31)
br label %_llgo_1
_llgo_17: ; preds = %_llgo_15
%33 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 10)
%34 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %33)
%35 = extractvalue { i64, i1 } %34, 0
%36 = extractvalue { i64, i1 } %34, 1
br i1 %36, label %_llgo_18, label %_llgo_19
_llgo_18: ; preds = %_llgo_17
call void @main.printuint(i64 %35)
br label %_llgo_1
_llgo_19: ; preds = %_llgo_17
%37 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 11)
%38 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %37)
%39 = extractvalue { i64, i1 } %38, 0
%40 = extractvalue { i64, i1 } %38, 1
br i1 %40, label %_llgo_20, label %_llgo_21
_llgo_20: ; preds = %_llgo_19
call void @main.printuint(i64 %39)
br label %_llgo_1
_llgo_21: ; preds = %_llgo_19
%41 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 12)
%42 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %41)
%43 = extractvalue { i64, i1 } %42, 0
%44 = extractvalue { i64, i1 } %42, 1
br i1 %44, label %_llgo_22, label %_llgo_23
_llgo_22: ; preds = %_llgo_21
call void @main.printuint(i64 %43)
br label %_llgo_1
_llgo_23: ; preds = %_llgo_21
%45 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 13)
%46 = call { float, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Float32"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %45)
%47 = extractvalue { float, i1 } %46, 0
%48 = extractvalue { float, i1 } %46, 1
br i1 %48, label %_llgo_24, label %_llgo_25
_llgo_24: ; preds = %_llgo_23
%49 = fpext float %47 to double
call void @main.printfloat(double %49)
br label %_llgo_1
_llgo_25: ; preds = %_llgo_23
%50 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 14)
%51 = call { double, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Float64"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %50)
%52 = extractvalue { double, i1 } %51, 0
%53 = extractvalue { double, i1 } %51, 1
br i1 %53, label %_llgo_26, label %_llgo_1
_llgo_26: ; preds = %_llgo_25
call void @main.printfloat(double %52)
br label %_llgo_1
}
define void @main.printsp() {
_llgo_0:
%0 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @8, i64 1)
%0 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @14, i64 1)
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %0)
ret void
}
@@ -587,8 +783,6 @@ _llgo_0:
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
declare i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice")
declare i32 @printf(ptr, ...)
declare void @"github.com/goplus/llgo/internal/runtime.init"()
@@ -599,12 +793,10 @@ declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64)
declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr, i64)
declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr, i64, i64, i64, i64, i64)
declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String")
declare ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String")
declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr, i64, i64, i64, i64, i64)
declare { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface", ptr)
declare { float, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Float32"(%"github.com/goplus/llgo/internal/runtime.iface", ptr)
declare { double, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Float64"(%"github.com/goplus/llgo/internal/runtime.iface", ptr)
declare { %"github.com/goplus/llgo/internal/runtime.String", i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2String"(%"github.com/goplus/llgo/internal/runtime.iface", ptr)

View File

@@ -48,7 +48,7 @@ _llgo_0:
define void @main.test(%"github.com/goplus/llgo/internal/runtime.Slice" %0) {
_llgo_0:
%1 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %0)
%1 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 1
br label %_llgo_1
_llgo_1: ; preds = %_llgo_2, %_llgo_0
@@ -58,7 +58,7 @@ _llgo_1: ; preds = %_llgo_2, %_llgo_0
br i1 %4, label %_llgo_2, label %_llgo_3
_llgo_2: ; preds = %_llgo_1
%5 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %0)
%5 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 0
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %5, i64 %3
%7 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %6, align 8
%8 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2)
@@ -80,10 +80,6 @@ declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llg
declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr, i64, i64, i64, i64, i64)
declare i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice")
declare ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice")
declare i64 @"github.com/goplus/llgo/internal/runtime.I2Int"(%"github.com/goplus/llgo/internal/runtime.iface", ptr)
declare i32 @printf(ptr, ...)

View File

@@ -13,7 +13,7 @@ _llgo_0:
br i1 %1, label %_llgo_1, label %_llgo_2
_llgo_1: ; preds = %_llgo_0
%2 = call ptr @sqlite3_errstr()
%2 = call ptr @sqlite3_errstr(i32 %0)
%3 = call i32 (ptr, ...) @printf(ptr @0, i32 %0, ptr %2)
call void @exit(i32 1)
br label %_llgo_2
@@ -45,11 +45,11 @@ _llgo_0:
%3 = extractvalue { ptr, i32 } %2, 0
%4 = extractvalue { ptr, i32 } %2, 1
call void @main.check(i32 %4)
%5 = call i32 @sqlite3_close()
%5 = call i32 @sqlite3_close(ptr %3)
ret void
}
declare ptr @sqlite3_errstr()
declare ptr @sqlite3_errstr(i32)
declare i32 @printf(ptr, ...)
@@ -59,4 +59,4 @@ declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare { ptr, i32 } @"github.com/goplus/llgo/x/sqlite.OpenV2"(ptr, i32, ptr)
declare i32 @sqlite3_close()
declare i32 @sqlite3_close(ptr)

15
cl/_testpy/callpy/in.go Normal file
View File

@@ -0,0 +1,15 @@
package main
import (
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/py"
"github.com/goplus/llgo/py/math"
"github.com/goplus/llgo/py/os"
)
func main() {
x := math.Sqrt(py.Float(2))
wd := os.Getcwd()
c.Printf(c.Str("sqrt(2) = %f\n"), x.Float64())
c.Printf(c.Str("cwd = %s\n"), wd.CStr())
}

74
cl/_testpy/callpy/out.ll Normal file
View File

@@ -0,0 +1,74 @@
; ModuleID = 'main'
source_filename = "main"
@"main.init$guard" = global ptr null
@__llgo_argc = global ptr null
@__llgo_argv = global ptr null
@__llgo_py.math.sqrt = linkonce global ptr null
@__llgo_py.os.getcwd = linkonce global ptr null
@0 = private unnamed_addr constant [14 x i8] c"sqrt(2) = %f\0A\00", align 1
@1 = private unnamed_addr constant [10 x i8] c"cwd = %s\0A\00", align 1
@__llgo_py.math = external global ptr
@2 = private unnamed_addr constant [5 x i8] c"sqrt\00", align 1
@__llgo_py.os = external global ptr
@3 = private unnamed_addr constant [7 x i8] c"getcwd\00", align 1
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
call void @"github.com/goplus/llgo/py/math.init"()
call void @"github.com/goplus/llgo/py/os.init"()
%1 = load ptr, ptr @__llgo_py.math, align 8
call void (ptr, ...) @llgoLoadPyModSyms(ptr %1, ptr @2, ptr @__llgo_py.math.sqrt, ptr null)
%2 = load ptr, ptr @__llgo_py.os, align 8
call void (ptr, ...) @llgoLoadPyModSyms(ptr %2, ptr @3, ptr @__llgo_py.os.getcwd, ptr null)
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main(i32 %0, ptr %1) {
_llgo_0:
call void @Py_Initialize()
store i32 %0, ptr @__llgo_argc, align 4
store ptr %1, ptr @__llgo_argv, align 8
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%2 = call ptr @PyFloat_FromDouble(double 2.000000e+00)
%3 = load ptr, ptr @__llgo_py.math.sqrt, align 8
%4 = call ptr @PyObject_CallOneArg(ptr %3, ptr %2)
%5 = load ptr, ptr @__llgo_py.os.getcwd, align 8
%6 = call ptr @PyObject_CallNoArgs(ptr %5)
%7 = call double @PyFloat_AsDouble(ptr %4)
%8 = call i32 (ptr, ...) @printf(ptr @0, double %7)
%9 = call ptr @PyUnicode_AsUTF8(ptr %6)
%10 = call i32 (ptr, ...) @printf(ptr @1, ptr %9)
ret void
}
declare void @"github.com/goplus/llgo/py/math.init"()
declare void @"github.com/goplus/llgo/py/os.init"()
declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare ptr @PyFloat_FromDouble(double)
declare ptr @PyObject_CallOneArg(ptr, ptr)
declare ptr @PyObject_CallNoArgs(ptr)
declare double @PyFloat_AsDouble(ptr)
declare i32 @printf(ptr, ...)
declare ptr @PyUnicode_AsUTF8(ptr)
declare void @llgoLoadPyModSyms(ptr, ...)
declare void @Py_Initialize()

12
cl/_testpy/gcd/in.go Normal file
View File

@@ -0,0 +1,12 @@
package main
import (
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/py"
"github.com/goplus/llgo/py/math"
)
func main() {
x := math.Gcd(py.Long(60), py.Long(20), py.Long(25))
c.Printf(c.Str("gcd(60, 20, 25) = %d\n"), x.Long())
}

59
cl/_testpy/gcd/out.ll Normal file
View File

@@ -0,0 +1,59 @@
; ModuleID = 'main'
source_filename = "main"
@"main.init$guard" = global ptr null
@__llgo_argc = global ptr null
@__llgo_argv = global ptr null
@__llgo_py.math.gcd = linkonce global ptr null
@0 = private unnamed_addr constant [22 x i8] c"gcd(60, 20, 25) = %d\0A\00", align 1
@__llgo_py.math = external global ptr
@1 = private unnamed_addr constant [4 x i8] c"gcd\00", align 1
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
call void @"github.com/goplus/llgo/py/math.init"()
%1 = load ptr, ptr @__llgo_py.math, align 8
call void (ptr, ...) @llgoLoadPyModSyms(ptr %1, ptr @1, ptr @__llgo_py.math.gcd, ptr null)
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main(i32 %0, ptr %1) {
_llgo_0:
call void @Py_Initialize()
store i32 %0, ptr @__llgo_argc, align 4
store ptr %1, ptr @__llgo_argv, align 8
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%2 = call ptr @PyLong_FromLong(i32 60)
%3 = call ptr @PyLong_FromLong(i32 20)
%4 = call ptr @PyLong_FromLong(i32 25)
%5 = load ptr, ptr @__llgo_py.math.gcd, align 8
%6 = call ptr (ptr, ...) @PyObject_CallFunctionObjArgs(ptr %5, ptr %2, ptr %3, ptr %4, ptr null)
%7 = call i32 @PyLong_AsLong(ptr %6)
%8 = call i32 (ptr, ...) @printf(ptr @0, i32 %7)
ret void
}
declare void @"github.com/goplus/llgo/py/math.init"()
declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare ptr @PyLong_FromLong(i32)
declare ptr @PyObject_CallFunctionObjArgs(ptr, ...)
declare i32 @PyLong_AsLong(ptr)
declare i32 @printf(ptr, ...)
declare void @llgoLoadPyModSyms(ptr, ...)
declare void @Py_Initialize()

14
cl/_testpy/math/in.go Normal file
View File

@@ -0,0 +1,14 @@
package math
import (
_ "unsafe"
"github.com/goplus/llgo/py"
)
const (
LLGoPackage = "py.math"
)
//go:linkname Sqrt py.sqrt
func Sqrt(x *py.Object) *py.Object

28
cl/_testpy/math/out.ll Normal file
View File

@@ -0,0 +1,28 @@
; ModuleID = 'math'
source_filename = "math"
@"math.init$guard" = global ptr null
@__llgo_py.math = linkonce global ptr null
@0 = private unnamed_addr constant [5 x i8] c"math\00", align 1
define void @math.init() {
_llgo_0:
%0 = load i1, ptr @"math.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"math.init$guard", align 1
%1 = load ptr, ptr @__llgo_py.math, align 8
%2 = icmp ne ptr %1, null
br i1 %2, label %_llgo_2, label %_llgo_3
_llgo_2: ; preds = %_llgo_3, %_llgo_1, %_llgo_0
ret void
_llgo_3: ; preds = %_llgo_1
%3 = call ptr @PyImport_ImportModule(ptr @0)
store ptr %3, ptr @__llgo_py.math, align 8
br label %_llgo_2
}
declare ptr @PyImport_ImportModule(ptr)

24
cl/_testpy/matrix/in.go Normal file
View File

@@ -0,0 +1,24 @@
package main
import (
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/py"
"github.com/goplus/llgo/py/numpy"
)
func main() {
a := py.List(
py.List(1.0, 2.0, 3.0),
py.List(4.0, 5.0, 6.0),
py.List(7.0, 8.0, 9.0),
)
b := py.List(
py.List(9.0, 8.0, 7.0),
py.List(6.0, 5.0, 4.0),
py.List(3.0, 2.0, 1.0),
)
x := numpy.Add(a, b)
c.Printf(c.Str("a = %s\n"), a.Str().CStr())
c.Printf(c.Str("a = %s\n"), b.Str().CStr())
c.Printf(c.Str("a+b = %s\n"), x.Str().CStr())
}

121
cl/_testpy/matrix/out.ll Normal file
View File

@@ -0,0 +1,121 @@
; ModuleID = 'main'
source_filename = "main"
@"main.init$guard" = global ptr null
@__llgo_argc = global ptr null
@__llgo_argv = global ptr null
@__llgo_py.numpy.add = linkonce global ptr null
@0 = private unnamed_addr constant [8 x i8] c"a = %s\0A\00", align 1
@1 = private unnamed_addr constant [8 x i8] c"a = %s\0A\00", align 1
@2 = private unnamed_addr constant [10 x i8] c"a+b = %s\0A\00", align 1
@__llgo_py.numpy = external global ptr
@3 = private unnamed_addr constant [4 x i8] c"add\00", align 1
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
call void @"github.com/goplus/llgo/py/numpy.init"()
%1 = load ptr, ptr @__llgo_py.numpy, align 8
call void (ptr, ...) @llgoLoadPyModSyms(ptr %1, ptr @3, ptr @__llgo_py.numpy.add, ptr null)
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main(i32 %0, ptr %1) {
_llgo_0:
call void @Py_Initialize()
store i32 %0, ptr @__llgo_argc, align 4
store ptr %1, ptr @__llgo_argv, align 8
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%2 = call ptr @PyList_New(i64 3)
%3 = call ptr @PyFloat_FromDouble(double 1.000000e+00)
%4 = call i32 @PyList_SetItem(ptr %2, i64 0, ptr %3)
%5 = call ptr @PyFloat_FromDouble(double 2.000000e+00)
%6 = call i32 @PyList_SetItem(ptr %2, i64 1, ptr %5)
%7 = call ptr @PyFloat_FromDouble(double 3.000000e+00)
%8 = call i32 @PyList_SetItem(ptr %2, i64 2, ptr %7)
%9 = call ptr @PyList_New(i64 3)
%10 = call ptr @PyFloat_FromDouble(double 4.000000e+00)
%11 = call i32 @PyList_SetItem(ptr %9, i64 0, ptr %10)
%12 = call ptr @PyFloat_FromDouble(double 5.000000e+00)
%13 = call i32 @PyList_SetItem(ptr %9, i64 1, ptr %12)
%14 = call ptr @PyFloat_FromDouble(double 6.000000e+00)
%15 = call i32 @PyList_SetItem(ptr %9, i64 2, ptr %14)
%16 = call ptr @PyList_New(i64 3)
%17 = call ptr @PyFloat_FromDouble(double 7.000000e+00)
%18 = call i32 @PyList_SetItem(ptr %16, i64 0, ptr %17)
%19 = call ptr @PyFloat_FromDouble(double 8.000000e+00)
%20 = call i32 @PyList_SetItem(ptr %16, i64 1, ptr %19)
%21 = call ptr @PyFloat_FromDouble(double 9.000000e+00)
%22 = call i32 @PyList_SetItem(ptr %16, i64 2, ptr %21)
%23 = call ptr @PyList_New(i64 3)
%24 = call i32 @PyList_SetItem(ptr %23, i64 0, ptr %2)
%25 = call i32 @PyList_SetItem(ptr %23, i64 1, ptr %9)
%26 = call i32 @PyList_SetItem(ptr %23, i64 2, ptr %16)
%27 = call ptr @PyList_New(i64 3)
%28 = call ptr @PyFloat_FromDouble(double 9.000000e+00)
%29 = call i32 @PyList_SetItem(ptr %27, i64 0, ptr %28)
%30 = call ptr @PyFloat_FromDouble(double 8.000000e+00)
%31 = call i32 @PyList_SetItem(ptr %27, i64 1, ptr %30)
%32 = call ptr @PyFloat_FromDouble(double 7.000000e+00)
%33 = call i32 @PyList_SetItem(ptr %27, i64 2, ptr %32)
%34 = call ptr @PyList_New(i64 3)
%35 = call ptr @PyFloat_FromDouble(double 6.000000e+00)
%36 = call i32 @PyList_SetItem(ptr %34, i64 0, ptr %35)
%37 = call ptr @PyFloat_FromDouble(double 5.000000e+00)
%38 = call i32 @PyList_SetItem(ptr %34, i64 1, ptr %37)
%39 = call ptr @PyFloat_FromDouble(double 4.000000e+00)
%40 = call i32 @PyList_SetItem(ptr %34, i64 2, ptr %39)
%41 = call ptr @PyList_New(i64 3)
%42 = call ptr @PyFloat_FromDouble(double 3.000000e+00)
%43 = call i32 @PyList_SetItem(ptr %41, i64 0, ptr %42)
%44 = call ptr @PyFloat_FromDouble(double 2.000000e+00)
%45 = call i32 @PyList_SetItem(ptr %41, i64 1, ptr %44)
%46 = call ptr @PyFloat_FromDouble(double 1.000000e+00)
%47 = call i32 @PyList_SetItem(ptr %41, i64 2, ptr %46)
%48 = call ptr @PyList_New(i64 3)
%49 = call i32 @PyList_SetItem(ptr %48, i64 0, ptr %27)
%50 = call i32 @PyList_SetItem(ptr %48, i64 1, ptr %34)
%51 = call i32 @PyList_SetItem(ptr %48, i64 2, ptr %41)
%52 = load ptr, ptr @__llgo_py.numpy.add, align 8
%53 = call ptr (ptr, ...) @PyObject_CallFunctionObjArgs(ptr %52, ptr %23, ptr %48, ptr null)
%54 = call ptr @PyObject_Str(ptr %23)
%55 = call ptr @PyUnicode_AsUTF8(ptr %54)
%56 = call i32 (ptr, ...) @printf(ptr @0, ptr %55)
%57 = call ptr @PyObject_Str(ptr %48)
%58 = call ptr @PyUnicode_AsUTF8(ptr %57)
%59 = call i32 (ptr, ...) @printf(ptr @1, ptr %58)
%60 = call ptr @PyObject_Str(ptr %53)
%61 = call ptr @PyUnicode_AsUTF8(ptr %60)
%62 = call i32 (ptr, ...) @printf(ptr @2, ptr %61)
ret void
}
declare void @"github.com/goplus/llgo/py/numpy.init"()
declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare ptr @PyList_New(i64)
declare ptr @PyFloat_FromDouble(double)
declare i32 @PyList_SetItem(ptr, i64, ptr)
declare ptr @PyObject_CallFunctionObjArgs(ptr, ...)
declare ptr @PyObject_Str(ptr)
declare ptr @PyUnicode_AsUTF8(ptr)
declare i32 @printf(ptr, ...)
declare void @llgoLoadPyModSyms(ptr, ...)
declare void @Py_Initialize()

10
cl/_testpy/pi/in.go Normal file
View File

@@ -0,0 +1,10 @@
package main
import (
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/py/math"
)
func main() {
c.Printf(c.Str("pi = %f\n"), math.Pi.Float64())
}

49
cl/_testpy/pi/out.ll Normal file
View File

@@ -0,0 +1,49 @@
; ModuleID = 'main'
source_filename = "main"
@"main.init$guard" = global ptr null
@__llgo_argc = global ptr null
@__llgo_argv = global ptr null
@0 = private unnamed_addr constant [9 x i8] c"pi = %f\0A\00", align 1
@__llgo_py.math = external global ptr
@1 = private unnamed_addr constant [3 x i8] c"pi\00", align 1
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
call void @"github.com/goplus/llgo/py/math.init"()
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main(i32 %0, ptr %1) {
_llgo_0:
call void @Py_Initialize()
store i32 %0, ptr @__llgo_argc, align 4
store ptr %1, ptr @__llgo_argv, align 8
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%2 = load ptr, ptr @__llgo_py.math, align 8
%3 = call ptr @PyObject_GetAttrString(ptr %2, ptr @1)
%4 = call double @PyFloat_AsDouble(ptr %3)
%5 = call i32 (ptr, ...) @printf(ptr @0, double %4)
ret void
}
declare void @"github.com/goplus/llgo/py/math.init"()
declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare ptr @PyObject_GetAttrString(ptr, ptr)
declare double @PyFloat_AsDouble(ptr)
declare i32 @printf(ptr, ...)
declare void @Py_Initialize()

12
cl/_testpy/pow/in.go Normal file
View File

@@ -0,0 +1,12 @@
package main
import (
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/py"
"github.com/goplus/llgo/py/math"
)
func main() {
x := math.Pow(py.Float(2), py.Float(3))
c.Printf(c.Str("pow(2, 3) = %f\n"), x.Float64())
}

58
cl/_testpy/pow/out.ll Normal file
View File

@@ -0,0 +1,58 @@
; ModuleID = 'main'
source_filename = "main"
@"main.init$guard" = global ptr null
@__llgo_argc = global ptr null
@__llgo_argv = global ptr null
@__llgo_py.math.pow = linkonce global ptr null
@0 = private unnamed_addr constant [16 x i8] c"pow(2, 3) = %f\0A\00", align 1
@__llgo_py.math = external global ptr
@1 = private unnamed_addr constant [4 x i8] c"pow\00", align 1
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
call void @"github.com/goplus/llgo/py/math.init"()
%1 = load ptr, ptr @__llgo_py.math, align 8
call void (ptr, ...) @llgoLoadPyModSyms(ptr %1, ptr @1, ptr @__llgo_py.math.pow, ptr null)
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main(i32 %0, ptr %1) {
_llgo_0:
call void @Py_Initialize()
store i32 %0, ptr @__llgo_argc, align 4
store ptr %1, ptr @__llgo_argv, align 8
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%2 = call ptr @PyFloat_FromDouble(double 2.000000e+00)
%3 = call ptr @PyFloat_FromDouble(double 3.000000e+00)
%4 = load ptr, ptr @__llgo_py.math.pow, align 8
%5 = call ptr (ptr, ...) @PyObject_CallFunctionObjArgs(ptr %4, ptr %2, ptr %3, ptr null)
%6 = call double @PyFloat_AsDouble(ptr %5)
%7 = call i32 (ptr, ...) @printf(ptr @0, double %6)
ret void
}
declare void @"github.com/goplus/llgo/py/math.init"()
declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare ptr @PyFloat_FromDouble(double)
declare ptr @PyObject_CallFunctionObjArgs(ptr, ...)
declare double @PyFloat_AsDouble(ptr)
declare i32 @printf(ptr, ...)
declare void @llgoLoadPyModSyms(ptr, ...)
declare void @Py_Initialize()

View File

@@ -34,7 +34,7 @@ _llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%2 = call %"github.com/goplus/llgo/internal/runtime.String" @main.hello()
%3 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %2)
%3 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %2, 1
%4 = add i64 %3, 1
%5 = alloca i8, i64 %4, align 1
%6 = call ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr %5, %"github.com/goplus/llgo/internal/runtime.String" %2)
@@ -46,8 +46,6 @@ declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/ll
declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String")
declare ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr, %"github.com/goplus/llgo/internal/runtime.String")
declare i32 @printf(ptr, ...)

View File

@@ -40,6 +40,12 @@ func main() {
string_len("hello"[1:])
string_len("hello"[1:2])
string_len("hello"[5:])
s = append(s, 5, 6, 7, 8)
out(len(s))
data := []byte{'a', 'b', 'c'}
data = append(data, "def"...)
out(len(data))
}
func string_len(s string) {

View File

@@ -14,7 +14,8 @@ source_filename = "main"
@1 = private unnamed_addr constant [6 x i8] c"hello\00", align 1
@2 = private unnamed_addr constant [6 x i8] c"hello\00", align 1
@3 = private unnamed_addr constant [6 x i8] c"hello\00", align 1
@4 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
@4 = private unnamed_addr constant [4 x i8] c"def\00", align 1
@5 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
define void @main.init() {
_llgo_0:
@@ -57,7 +58,7 @@ _llgo_0:
store i64 2, ptr %10, align 4
store i64 3, ptr %11, align 4
store i64 4, ptr %12, align 4
%13 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
%13 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 1
call void @main.out(i64 %13)
%14 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
%15 = getelementptr inbounds i64, ptr %14, i64 0
@@ -69,90 +70,119 @@ _llgo_0:
%18 = getelementptr inbounds i64, ptr %14, i64 3
store i64 4, ptr %18, align 4
%19 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %14, i64 8, i64 4, i64 0, i64 4, i64 4)
%20 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %19)
%20 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %19, 1
call void @main.out(i64 %20)
call void @main.out(i64 4)
call void @main.out(i64 4)
call void @main.out(i64 4)
%21 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
%21 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 2
call void @main.out(i64 %21)
call void @main.out(i64 4)
call void @main.out(i64 4)
%22 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
%23 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
%24 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
%22 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 2
%23 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 2
%24 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 0
%25 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %24, i64 8, i64 %22, i64 1, i64 %23, i64 %22)
%26 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %25)
%26 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %25, 1
call void @main.out(i64 %26)
%27 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
%28 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
%29 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
%27 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 2
%28 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 2
%29 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 0
%30 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %29, i64 8, i64 %27, i64 1, i64 %28, i64 %27)
%31 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %30)
%31 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %30, 2
call void @main.out(i64 %31)
%32 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
%33 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
%32 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 2
%33 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 0
%34 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %33, i64 8, i64 %32, i64 1, i64 2, i64 %32)
%35 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %34)
%35 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %34, 1
call void @main.out(i64 %35)
%36 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
%37 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
%36 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 2
%37 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 0
%38 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %37, i64 8, i64 %36, i64 1, i64 2, i64 %36)
%39 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %38)
%39 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %38, 2
call void @main.out(i64 %39)
%40 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
%41 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
%40 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 2
%41 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 0
%42 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %41, i64 8, i64 %40, i64 1, i64 2, i64 2)
%43 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %42)
%43 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %42, 1
call void @main.out(i64 %43)
%44 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
%45 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
%44 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 2
%45 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 0
%46 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %45, i64 8, i64 %44, i64 1, i64 2, i64 2)
%47 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %46)
%47 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %46, 2
call void @main.out(i64 %47)
%48 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %8, i64 8, i64 4, i64 1, i64 4, i64 4)
%49 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %48)
%49 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %48, 1
call void @main.out(i64 %49)
%50 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %8, i64 8, i64 4, i64 1, i64 4, i64 4)
%51 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %50)
%51 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %50, 2
call void @main.out(i64 %51)
%52 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %8, i64 8, i64 4, i64 1, i64 2, i64 4)
%53 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %52)
%53 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %52, 1
call void @main.out(i64 %53)
%54 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %8, i64 8, i64 4, i64 1, i64 2, i64 4)
%55 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %54)
%55 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %54, 2
call void @main.out(i64 %55)
%56 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %8, i64 8, i64 4, i64 1, i64 2, i64 2)
%57 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %56)
%57 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %56, 1
call void @main.out(i64 %57)
%58 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %8, i64 8, i64 4, i64 1, i64 2, i64 2)
%59 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %58)
%59 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %58, 2
call void @main.out(i64 %59)
%60 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @0, i64 5)
call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %60)
%61 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @1, i64 5)
%62 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %61)
%62 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %61, 1
%63 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %61, i64 1, i64 %62)
call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %63)
%64 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @2, i64 5)
%65 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %64, i64 1, i64 2)
call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %65)
%66 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @3, i64 5)
%67 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %66)
%67 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %66, 1
%68 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %66, i64 5, i64 %67)
call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %68)
%69 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
%70 = getelementptr inbounds i64, ptr %69, i64 0
store i64 5, ptr %70, align 4
%71 = getelementptr inbounds i64, ptr %69, i64 1
store i64 6, ptr %71, align 4
%72 = getelementptr inbounds i64, ptr %69, i64 2
store i64 7, ptr %72, align 4
%73 = getelementptr inbounds i64, ptr %69, i64 3
store i64 8, ptr %73, align 4
%74 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %69, i64 8, i64 4, i64 0, i64 4, i64 4)
%75 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %74, 0
%76 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %74, 1
%77 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.SliceAppend"(%"github.com/goplus/llgo/internal/runtime.Slice" %7, ptr %75, i64 %76, i64 8)
%78 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %77, 1
call void @main.out(i64 %78)
%79 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 3)
%80 = getelementptr inbounds i8, ptr %79, i64 0
store i8 97, ptr %80, align 1
%81 = getelementptr inbounds i8, ptr %79, i64 1
store i8 98, ptr %81, align 1
%82 = getelementptr inbounds i8, ptr %79, i64 2
store i8 99, ptr %82, align 1
%83 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %79, i64 1, i64 3, i64 0, i64 3, i64 3)
%84 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @4, i64 3)
%85 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %84, 0
%86 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %84, 1
%87 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.SliceAppend"(%"github.com/goplus/llgo/internal/runtime.Slice" %83, ptr %85, i64 %86, i64 1)
%88 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %87, 1
call void @main.out(i64 %88)
ret void
}
define void @main.out(i64 %0) {
_llgo_0:
%1 = call i32 (ptr, ...) @printf(ptr @4, i64 %0)
%1 = call i32 (ptr, ...) @printf(ptr @5, i64 %0)
ret void
}
define void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %0) {
_llgo_0:
%1 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %0)
%1 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %0, 1
call void @main.out(i64 %1)
ret void
}
@@ -163,16 +193,10 @@ declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr, i64, i64, i64, i64, i64)
declare i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice")
declare i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice")
declare ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice")
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64)
declare i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String")
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String", i64, i64)
declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.SliceAppend"(%"github.com/goplus/llgo/internal/runtime.Slice", ptr, i64, i64)
declare i32 @printf(ptr, ...)

View File

@@ -11,6 +11,10 @@ func concat(args ...string) (ret string) {
return
}
func info(s string) string {
return "" + s + "..."
}
func main() {
result := concat("Hello", " ", "World")
c.Fprintf(c.Stderr, c.Str("Hi, %s\n"), c.AllocaCStr(result))

View File

@@ -6,17 +6,19 @@ source_filename = "main"
@"main.init$guard" = global ptr null
@0 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
@1 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
@2 = private unnamed_addr constant [4 x i8] c"...\00", align 1
@__llgo_argc = global ptr null
@__llgo_argv = global ptr null
@1 = private unnamed_addr constant [6 x i8] c"Hello\00", align 1
@2 = private unnamed_addr constant [2 x i8] c" \00", align 1
@3 = private unnamed_addr constant [6 x i8] c"World\00", align 1
@3 = private unnamed_addr constant [6 x i8] c"Hello\00", align 1
@4 = private unnamed_addr constant [2 x i8] c" \00", align 1
@5 = private unnamed_addr constant [6 x i8] c"World\00", align 1
@__stderrp = external global ptr
@4 = private unnamed_addr constant [8 x i8] c"Hi, %s\0A\00", align 1
@6 = private unnamed_addr constant [8 x i8] c"Hi, %s\0A\00", align 1
define %"github.com/goplus/llgo/internal/runtime.String" @main.concat(%"github.com/goplus/llgo/internal/runtime.Slice" %0) {
_llgo_0:
%1 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %0)
%1 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 1
%2 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @0, i64 0)
%3 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %2, 0
%4 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %2, 1
@@ -37,7 +39,7 @@ _llgo_1: ; preds = %_llgo_2, %_llgo_0
br i1 %13, label %_llgo_2, label %_llgo_3
_llgo_2: ; preds = %_llgo_1
%14 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %0)
%14 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 0
%15 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %14, i64 %12
%16 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %15, align 8
%17 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringCat"(%"github.com/goplus/llgo/internal/runtime.String" %11, %"github.com/goplus/llgo/internal/runtime.String" %16)
@@ -49,6 +51,15 @@ _llgo_3: ; preds = %_llgo_1
ret %"github.com/goplus/llgo/internal/runtime.String" %11
}
define %"github.com/goplus/llgo/internal/runtime.String" @main.info(%"github.com/goplus/llgo/internal/runtime.String" %0) {
_llgo_0:
%1 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @1, i64 0)
%2 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringCat"(%"github.com/goplus/llgo/internal/runtime.String" %1, %"github.com/goplus/llgo/internal/runtime.String" %0)
%3 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @2, i64 3)
%4 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringCat"(%"github.com/goplus/llgo/internal/runtime.String" %2, %"github.com/goplus/llgo/internal/runtime.String" %3)
ret %"github.com/goplus/llgo/internal/runtime.String" %4
}
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
@@ -70,29 +81,25 @@ _llgo_0:
call void @main.init()
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 48)
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i64 0
%4 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @1, i64 5)
%4 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @3, i64 5)
store %"github.com/goplus/llgo/internal/runtime.String" %4, ptr %3, align 8
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i64 1
%6 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @2, i64 1)
%6 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @4, i64 1)
store %"github.com/goplus/llgo/internal/runtime.String" %6, ptr %5, align 8
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i64 2
%8 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @3, i64 5)
%8 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @5, i64 5)
store %"github.com/goplus/llgo/internal/runtime.String" %8, ptr %7, align 8
%9 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %2, i64 16, i64 3, i64 0, i64 3, i64 3)
%10 = call %"github.com/goplus/llgo/internal/runtime.String" @main.concat(%"github.com/goplus/llgo/internal/runtime.Slice" %9)
%11 = load ptr, ptr @__stderrp, align 8
%12 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %10)
%12 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %10, 1
%13 = add i64 %12, 1
%14 = alloca i8, i64 %13, align 1
%15 = call ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr %14, %"github.com/goplus/llgo/internal/runtime.String" %10)
%16 = call i32 (ptr, ptr, ...) @fprintf(ptr %11, ptr @4, ptr %15)
%16 = call i32 (ptr, ptr, ...) @fprintf(ptr %11, ptr @6, ptr %15)
ret void
}
declare i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice")
declare ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice")
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringCat"(%"github.com/goplus/llgo/internal/runtime.String", %"github.com/goplus/llgo/internal/runtime.String")
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64)
@@ -103,8 +110,6 @@ declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr, i64, i64, i64, i64, i64)
declare i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String")
declare ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr, %"github.com/goplus/llgo/internal/runtime.String")
declare i32 @fprintf(ptr, ptr, ...)

View File

@@ -119,12 +119,12 @@ _llgo_0:
%61 = load i64, ptr %60, align 4
%62 = call i32 (ptr, ...) @printf(ptr @3, i64 %61)
%63 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @5, i64 6)
%64 = call ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String" %63)
%64 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %63, 0
%65 = getelementptr inbounds i8, ptr %64, i64 2
%66 = load i8, ptr %65, align 1
%67 = call i32 (ptr, ...) @printf(ptr @4, i8 %66)
%68 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @7, i64 6)
%69 = call ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String" %68)
%69 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %68, 0
%70 = getelementptr inbounds i8, ptr %69, i64 1
%71 = load i8, ptr %70, align 1
%72 = call i32 (ptr, ...) @printf(ptr @6, i8 %71)
@@ -138,5 +138,3 @@ declare ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr, i64)
declare i32 @printf(ptr, ...)
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64)
declare ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String")

View File

@@ -16,7 +16,7 @@ _llgo_0:
%2 = mul i64 %0, 4
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 %2)
%4 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice"(ptr %3, i64 %0, i64 %0)
%5 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %4)
%5 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %4, 1
br label %_llgo_1
_llgo_1: ; preds = %_llgo_2, %_llgo_0
@@ -29,7 +29,7 @@ _llgo_2: ; preds = %_llgo_1
%9 = extractvalue { ptr, ptr } %1, 1
%10 = extractvalue { ptr, ptr } %1, 0
%11 = call i32 %10(ptr %9)
%12 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %4)
%12 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %4, 0
%13 = getelementptr inbounds i32, ptr %12, i64 %7
store i32 %11, ptr %13, align 4
br label %_llgo_1
@@ -76,7 +76,7 @@ _llgo_0:
store ptr null, ptr %4, align 8
%5 = load { ptr, ptr }, ptr %2, align 8
%6 = call %"github.com/goplus/llgo/internal/runtime.Slice" @main.genInts(i64 5, { ptr, ptr } %5)
%7 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %6)
%7 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %6, 1
br label %_llgo_1
_llgo_1: ; preds = %_llgo_2, %_llgo_0
@@ -86,7 +86,7 @@ _llgo_1: ; preds = %_llgo_2, %_llgo_0
br i1 %10, label %_llgo_2, label %_llgo_3
_llgo_2: ; preds = %_llgo_1
%11 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %6)
%11 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %6, 0
%12 = getelementptr inbounds i32, ptr %11, i64 %9
%13 = load i32, ptr %12, align 4
%14 = call i32 (ptr, ...) @printf(ptr @0, i32 %13)
@@ -105,7 +105,7 @@ _llgo_3: ; preds = %_llgo_1
store ptr %16, ptr %20, align 8
%21 = load { ptr, ptr }, ptr %18, align 8
%22 = call %"github.com/goplus/llgo/internal/runtime.Slice" @main.genInts(i64 5, { ptr, ptr } %21)
%23 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %22)
%23 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %22, 1
br label %_llgo_4
_llgo_4: ; preds = %_llgo_5, %_llgo_3
@@ -115,7 +115,7 @@ _llgo_4: ; preds = %_llgo_5, %_llgo_3
br i1 %26, label %_llgo_5, label %_llgo_6
_llgo_5: ; preds = %_llgo_4
%27 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %22)
%27 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %22, 0
%28 = getelementptr inbounds i32, ptr %27, i64 %25
%29 = load i32, ptr %28, align 4
%30 = call i32 (ptr, ...) @printf(ptr @1, i32 %29)
@@ -135,7 +135,7 @@ _llgo_6: ; preds = %_llgo_4
store ptr %33, ptr %37, align 8
%38 = load { ptr, ptr }, ptr %35, align 8
%39 = call %"github.com/goplus/llgo/internal/runtime.Slice" @main.genInts(i64 5, { ptr, ptr } %38)
%40 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %39)
%40 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %39, 1
br label %_llgo_7
_llgo_7: ; preds = %_llgo_8, %_llgo_6
@@ -145,7 +145,7 @@ _llgo_7: ; preds = %_llgo_8, %_llgo_6
br i1 %43, label %_llgo_8, label %_llgo_9
_llgo_8: ; preds = %_llgo_7
%44 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %39)
%44 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %39, 0
%45 = getelementptr inbounds i32, ptr %44, i64 %42
%46 = load i32, ptr %45, align 4
%47 = call i32 (ptr, ...) @printf(ptr @2, i32 %46)
@@ -159,10 +159,6 @@ declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice"(ptr, i64, i64)
declare i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice")
declare ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice")
declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare i32 @rand()

39
cl/_testrt/named/in.go Normal file
View File

@@ -0,0 +1,39 @@
package main
import "github.com/goplus/llgo/internal/runtime/c"
type mSpanList struct {
first *mspan
last *mspan
}
type minfo struct {
span *mspan
info int
}
type mspan struct {
next *mspan
prev *mspan
list *mSpanList
info minfo
value int
check func(int) int
}
func main() {
m := &mspan{}
m.value = 100
m.next = &mspan{}
m.next.value = 200
m.list = &mSpanList{}
m.list.last = &mspan{}
m.list.last.value = 300
m.info.info = 10
m.info.span = m
m.check = func(n int) int {
return m.value * n
}
c.Printf(c.Str("%d %d %d %d %d %d\n"), m.next.value, m.list.last.value, m.info.info,
m.info.span.value, m.check(-2), m.info.span.check(-3))
}

143
cl/_testrt/named/out.ll Normal file
View File

@@ -0,0 +1,143 @@
; ModuleID = 'main'
source_filename = "main"
%main.mspan = type { ptr, ptr, ptr, %main.minfo, i64, { ptr, ptr } }
%main.minfo = type { ptr, i64 }
%main.mSpanList = type { ptr, ptr }
@"main.init$guard" = global ptr null
@__llgo_argc = global ptr null
@__llgo_argv = global ptr null
@0 = private unnamed_addr constant [19 x i8] c"%d %d %d %d %d %d\0A\00", align 1
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main(i32 %0, ptr %1) {
_llgo_0:
store i32 %0, ptr @__llgo_argc, align 4
store ptr %1, ptr @__llgo_argv, align 8
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 8)
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 64)
store ptr %3, ptr %2, align 8
%4 = load ptr, ptr %2, align 8
%5 = getelementptr inbounds %main.mspan, ptr %4, i32 0, i32 4
store i64 100, ptr %5, align 4
%6 = load ptr, ptr %2, align 8
%7 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 64)
%8 = getelementptr inbounds %main.mspan, ptr %6, i32 0, i32 0
store ptr %7, ptr %8, align 8
%9 = load ptr, ptr %2, align 8
%10 = getelementptr inbounds %main.mspan, ptr %9, i32 0, i32 0
%11 = load ptr, ptr %10, align 8
%12 = getelementptr inbounds %main.mspan, ptr %11, i32 0, i32 4
store i64 200, ptr %12, align 4
%13 = load ptr, ptr %2, align 8
%14 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 16)
%15 = getelementptr inbounds %main.mspan, ptr %13, i32 0, i32 2
store ptr %14, ptr %15, align 8
%16 = load ptr, ptr %2, align 8
%17 = getelementptr inbounds %main.mspan, ptr %16, i32 0, i32 2
%18 = load ptr, ptr %17, align 8
%19 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 64)
%20 = getelementptr inbounds %main.mSpanList, ptr %18, i32 0, i32 1
store ptr %19, ptr %20, align 8
%21 = load ptr, ptr %2, align 8
%22 = getelementptr inbounds %main.mspan, ptr %21, i32 0, i32 2
%23 = load ptr, ptr %22, align 8
%24 = getelementptr inbounds %main.mSpanList, ptr %23, i32 0, i32 1
%25 = load ptr, ptr %24, align 8
%26 = getelementptr inbounds %main.mspan, ptr %25, i32 0, i32 4
store i64 300, ptr %26, align 4
%27 = load ptr, ptr %2, align 8
%28 = getelementptr inbounds %main.mspan, ptr %27, i32 0, i32 3
%29 = getelementptr inbounds %main.minfo, ptr %28, i32 0, i32 1
store i64 10, ptr %29, align 4
%30 = load ptr, ptr %2, align 8
%31 = getelementptr inbounds %main.mspan, ptr %30, i32 0, i32 3
%32 = load ptr, ptr %2, align 8
%33 = getelementptr inbounds %main.minfo, ptr %31, i32 0, i32 0
store ptr %32, ptr %33, align 8
%34 = load ptr, ptr %2, align 8
%35 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8)
%36 = getelementptr inbounds { ptr }, ptr %35, i32 0, i32 0
store ptr %2, ptr %36, align 8
%37 = alloca { ptr, ptr }, align 8
%38 = getelementptr inbounds { ptr, ptr }, ptr %37, i32 0, i32 0
store ptr @"main.main$1", ptr %38, align 8
%39 = getelementptr inbounds { ptr, ptr }, ptr %37, i32 0, i32 1
store ptr %35, ptr %39, align 8
%40 = load { ptr, ptr }, ptr %37, align 8
%41 = getelementptr inbounds %main.mspan, ptr %34, i32 0, i32 5
store { ptr, ptr } %40, ptr %41, align 8
%42 = load ptr, ptr %2, align 8
%43 = getelementptr inbounds %main.mspan, ptr %42, i32 0, i32 0
%44 = load ptr, ptr %43, align 8
%45 = getelementptr inbounds %main.mspan, ptr %44, i32 0, i32 4
%46 = load i64, ptr %45, align 4
%47 = load ptr, ptr %2, align 8
%48 = getelementptr inbounds %main.mspan, ptr %47, i32 0, i32 2
%49 = load ptr, ptr %48, align 8
%50 = getelementptr inbounds %main.mSpanList, ptr %49, i32 0, i32 1
%51 = load ptr, ptr %50, align 8
%52 = getelementptr inbounds %main.mspan, ptr %51, i32 0, i32 4
%53 = load i64, ptr %52, align 4
%54 = load ptr, ptr %2, align 8
%55 = getelementptr inbounds %main.mspan, ptr %54, i32 0, i32 3
%56 = getelementptr inbounds %main.minfo, ptr %55, i32 0, i32 1
%57 = load i64, ptr %56, align 4
%58 = load ptr, ptr %2, align 8
%59 = getelementptr inbounds %main.mspan, ptr %58, i32 0, i32 3
%60 = getelementptr inbounds %main.minfo, ptr %59, i32 0, i32 0
%61 = load ptr, ptr %60, align 8
%62 = getelementptr inbounds %main.mspan, ptr %61, i32 0, i32 4
%63 = load i64, ptr %62, align 4
%64 = load ptr, ptr %2, align 8
%65 = getelementptr inbounds %main.mspan, ptr %64, i32 0, i32 5
%66 = load { ptr, ptr }, ptr %65, align 8
%67 = extractvalue { ptr, ptr } %66, 1
%68 = extractvalue { ptr, ptr } %66, 0
%69 = call i64 %68(ptr %67, i64 -2)
%70 = load ptr, ptr %2, align 8
%71 = getelementptr inbounds %main.mspan, ptr %70, i32 0, i32 3
%72 = getelementptr inbounds %main.minfo, ptr %71, i32 0, i32 0
%73 = load ptr, ptr %72, align 8
%74 = getelementptr inbounds %main.mspan, ptr %73, i32 0, i32 5
%75 = load { ptr, ptr }, ptr %74, align 8
%76 = extractvalue { ptr, ptr } %75, 1
%77 = extractvalue { ptr, ptr } %75, 0
%78 = call i64 %77(ptr %76, i64 -3)
%79 = call i32 (ptr, ...) @printf(ptr @0, i64 %46, i64 %53, i64 %57, i64 %63, i64 %69, i64 %78)
ret void
}
declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
define i64 @"main.main$1"(ptr %0, i64 %1) {
_llgo_0:
%2 = load { ptr }, ptr %0, align 8
%3 = extractvalue { ptr } %2, 0
%4 = load ptr, ptr %3, align 8
%5 = getelementptr inbounds %main.mspan, ptr %4, i32 0, i32 4
%6 = load i64, ptr %5, align 4
%7 = mul i64 %6, %1
ret i64 %7
}
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64)
declare i32 @printf(ptr, ...)

View File

@@ -44,7 +44,7 @@ _llgo_0:
define i64 @main.sum(%"github.com/goplus/llgo/internal/runtime.Slice" %0) {
_llgo_0:
%1 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %0)
%1 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 1
br label %_llgo_1
_llgo_1: ; preds = %_llgo_2, %_llgo_0
@@ -55,7 +55,7 @@ _llgo_1: ; preds = %_llgo_2, %_llgo_0
br i1 %5, label %_llgo_2, label %_llgo_3
_llgo_2: ; preds = %_llgo_1
%6 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %0)
%6 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 0
%7 = getelementptr inbounds i64, ptr %6, i64 %4
%8 = load i64, ptr %7, align 4
%9 = add i64 %2, %8
@@ -72,7 +72,3 @@ declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr, i64, i64, i64, i64, i64)
declare i32 @printf(ptr, ...)
declare i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice")
declare ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice")

View File

@@ -226,5 +226,5 @@ func TestErrVarOf(t *testing.T) {
}
ssaPkg := &ssa.Package{Pkg: pkgTypes}
g := &ssa.Global{Pkg: ssaPkg}
ctx.varOf(g)
ctx.varOf(nil, g)
}

View File

@@ -147,11 +147,23 @@ func TestCompileEx(t *testing.T, src any, fname, expected string) {
}
return rt
})
prog.SetPython(func() *types.Package {
rt, err := imp.Import(llssa.PkgPython)
if err != nil {
t.Fatal("load python failed:", err)
}
return rt
})
ret, err := cl.NewPackage(prog, foo, files)
if err != nil {
t.Fatal("cl.NewPackage failed:", err)
}
if prog.NeedPyInit { // call PyInit if needed
ret.PyInit()
}
if v := ret.String(); v != expected {
t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected)
}

View File

@@ -123,6 +123,7 @@ type instrOrValue interface {
const (
PkgNormal = iota
PkgLLGo
PkgPyModule // py.<module>
PkgNoInit // noinit: a package that don't need to be initialized
PkgDeclOnly // decl: a package that only have declarations
PkgLinkIR // link llvm ir (.ll)
@@ -142,6 +143,7 @@ type context struct {
goProg *ssa.Program
goTyps *types.Package
goPkg *ssa.Package
pyMod string
link map[string]string // pkgPath.nameInPkg => linkname
loaded map[*types.Package]*pkgInfo // loaded packages
bvals map[ssa.Value]llssa.Expr // block values
@@ -183,7 +185,7 @@ func (p *context) compileMethods(pkg llssa.Package, typ types.Type) {
func (p *context) compileGlobal(pkg llssa.Package, gbl *ssa.Global) {
typ := gbl.Type()
name, vtype := p.varName(gbl.Pkg.Pkg, gbl)
if ignoreName(name) || checkCgo(gbl.Name()) {
if vtype == pyVar || ignoreName(name) || checkCgo(gbl.Name()) {
return
}
if debugInstr {
@@ -209,14 +211,21 @@ var (
argvTy = types.NewPointer(types.NewPointer(types.Typ[types.Int8]))
)
func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) llssa.Function {
func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Function, llssa.PyObjRef, int) {
pkgTypes, name, ftype := p.funcName(f, true)
if ftype != goFunc {
return nil
/*
if ftype == pyFunc {
// TODO(xsw): pyMod == ""
fnName := pysymPrefix + p.pyMod + "." + name
return nil, pkg.NewPyFunc(fnName, f.Signature, call), pyFunc
}
*/
return nil, nil, ignoredFunc
}
fn := pkg.FuncOf(name)
if fn != nil && fn.HasBody() {
return fn
return fn, nil, goFunc
}
var sig = f.Signature
@@ -229,7 +238,7 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) llssa.Func
sig = llssa.FuncAddCtx(ctx, sig)
} else {
if debugInstr {
log.Println("==> NewFunc", name, "type:", sig.Recv(), sig)
log.Println("==> NewFunc", name, "type:", sig.Recv(), sig, "ftype:", ftype)
}
}
if fn == nil {
@@ -262,21 +271,34 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) llssa.Func
off[i] = p.compilePhis(b, block)
}
for i, block := range f.Blocks {
p.compileBlock(b, block, off[i], i == 0 && name == "main")
doMainInit := (i == 0 && name == "main")
doModInit := (i == 1 && f.Name() == "init" && sig.Recv() == nil)
p.compileBlock(b, block, off[i], doMainInit, doModInit)
}
for _, phi := range p.phis {
phi()
}
})
}
return fn
return fn, nil, goFunc
}
// funcOf returns a function by name and set ftype = goFunc, cFunc, etc.
// or returns nil and set ftype = llgoCstr, llgoAlloca, llgoUnreachable, etc.
func (p *context) funcOf(fn *ssa.Function) (ret llssa.Function, ftype int) {
_, name, ftype := p.funcName(fn, false)
if ftype == llgoInstr {
func (p *context) funcOf(fn *ssa.Function) (aFn llssa.Function, pyFn llssa.PyObjRef, ftype int) {
pkgTypes, name, ftype := p.funcName(fn, false)
switch ftype {
case pyFunc:
if kind, mod := pkgKindByScope(pkgTypes.Scope()); kind == PkgPyModule {
pkg := p.pkg
fnName := pysymPrefix + mod + "." + name
if pyFn = pkg.PyObjOf(fnName); pyFn == nil {
pyFn = pkg.PyNewFunc(fnName, fn.Signature, true)
return
}
}
ftype = ignoredFunc
case llgoInstr:
switch name {
case "cstr":
ftype = llgoCstr
@@ -288,31 +310,73 @@ func (p *context) funcOf(fn *ssa.Function) (ret llssa.Function, ftype int) {
ftype = llgoAlloca
case "allocaCStr":
ftype = llgoAllocaCStr
case "stringData":
ftype = llgoStringData
case "pyList":
ftype = llgoPyList
case "unreachable":
ftype = llgoUnreachable
case "bitCastTo64F":
ftype = llgoBitCastTo64F
case "bitCastTo32F":
ftype = llgoBitCastTo32F
default:
panic("unknown llgo instruction: " + name)
}
} else {
default:
pkg := p.pkg
if ret = pkg.FuncOf(name); ret == nil && len(fn.FreeVars) == 0 {
if aFn = pkg.FuncOf(name); aFn == nil {
if len(fn.FreeVars) > 0 {
return nil, nil, ignoredFunc
}
sig := fn.Signature
ret = pkg.NewFuncEx(name, sig, llssa.Background(ftype), false)
aFn = pkg.NewFuncEx(name, sig, llssa.Background(ftype), false)
}
}
return
}
func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, doInit bool) llssa.BasicBlock {
ret := p.fn.Block(block.Index)
func modOf(name string) string {
if pos := strings.LastIndexByte(name, '.'); pos > 0 {
return name[:pos]
}
return ""
}
func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, doMainInit, doModInit bool) llssa.BasicBlock {
var last int
var pyModInit bool
var prog = p.prog
var pkg = p.pkg
var instrs = block.Instrs[n:]
var ret = p.fn.Block(block.Index)
b.SetBlock(ret)
if doInit {
prog := p.prog
pkg := p.pkg
if doModInit {
if pyModInit = p.pyMod != ""; pyModInit {
last = len(instrs) - 1
instrs = instrs[:last]
} else {
// TODO(xsw): confirm pyMod don't need to call LoadPyModSyms
p.inits = append(p.inits, func() {
if objs := pkg.PyObjs(); len(objs) > 0 {
mods := make(map[string][]llssa.PyObjRef)
for name, obj := range objs {
modName := modOf(name)
mods[modName] = append(mods[modName], obj)
}
// sort by module name
modNames := make([]string, 0, len(mods))
for modName := range mods {
modNames = append(modNames, modName)
}
sort.Strings(modNames)
b.SetBlockEx(ret, llssa.AfterInit)
for _, modName := range modNames {
objs := mods[modName]
b.PyLoadModSyms(modName, objs...)
}
}
})
}
} else if doMainInit {
fn := p.fn
argc := pkg.NewVar("__llgo_argc", types.NewPointer(types.Typ[types.Int32]), llssa.InC)
argv := pkg.NewVar("__llgo_argv", types.NewPointer(argvTy), llssa.InC)
@@ -323,9 +387,23 @@ func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, do
callRuntimeInit(b, pkg)
b.Call(pkg.FuncOf("main.init").Expr)
}
for _, instr := range block.Instrs[n:] {
for _, instr := range instrs {
p.compileInstr(b, instr)
}
if pyModInit {
jump := block.Instrs[n+last].(*ssa.Jump)
jumpTo := p.jumpTo(jump)
modPath := p.pyMod
modName := pysymPrefix + modPath
modPtr := pkg.PyNewModVar(modName, true).Expr
mod := b.Load(modPtr)
cond := b.BinOp(token.NEQ, mod, prog.Null(mod.Type))
newBlk := p.fn.MakeBlock()
b.If(cond, jumpTo, newBlk)
b.SetBlock(newBlk)
b.Store(modPtr, b.PyImportMod(modPath))
b.Jump(jumpTo)
}
return ret
}
@@ -334,8 +412,7 @@ const (
)
func callRuntimeInit(b llssa.Builder, pkg llssa.Package) {
sig := types.NewSignatureType(nil, nil, nil, nil, nil, false)
fn := pkg.NewFunc(RuntimeInit, sig, llssa.InC) // don't need to convert runtime.init
fn := pkg.NewFunc(RuntimeInit, llssa.NoArgsNoRet, llssa.InC) // don't need to convert runtime.init
b.Call(fn.Expr)
}
@@ -434,6 +511,15 @@ func (p *context) allocaCStr(b llssa.Builder, args []ssa.Value) (ret llssa.Expr)
panic("allocaCStr(s string): invalid arguments")
}
// func stringData(s string) *int8
func (p *context) stringData(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
if len(args) == 1 {
s := p.compileValue(b, args[0])
return b.StringData(s)
}
panic("stringData(s string): invalid arguments")
}
func isPhi(i ssa.Instruction) bool {
_, ok := i.(*ssa.Phi)
return ok
@@ -441,7 +527,7 @@ func isPhi(i ssa.Instruction) bool {
func (p *context) compilePhis(b llssa.Builder, block *ssa.BasicBlock) int {
ret := p.fn.Block(block.Index)
b.SetBlock(ret)
b.SetBlockEx(ret, llssa.AtEnd)
if ninstr := len(block.Instrs); ninstr > 0 {
if isPhi(block.Instrs[0]) {
n := 1
@@ -510,11 +596,17 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
ret = b.BuiltinCall(fn, args...)
}
case *ssa.Function:
fn, ftype := p.compileFunction(cv)
aFn, pyFn, ftype := p.compileFunction(cv)
switch ftype {
case goFunc, cFunc:
args := p.compileValues(b, args, kind)
ret = b.Call(fn.Expr, args...)
ret = b.Call(aFn.Expr, args...)
case pyFunc:
args := p.compileValues(b, args, kind)
ret = b.Call(pyFn.Expr, args...)
case llgoPyList:
args := p.compileValues(b, args, fnHasVArg)
ret = b.PyList(args...)
case llgoCstr:
ret = cstr(b, args)
case llgoAdvance:
@@ -525,12 +617,10 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
ret = p.alloca(b, args)
case llgoAllocaCStr:
ret = p.allocaCStr(b, args)
case llgoStringData:
ret = p.stringData(b, args)
case llgoUnreachable: // func unreachable()
b.Unreachable()
case llgoBitCastTo32F:
ret = b.BitCast(p.compileValue(b, args[0]), b.Prog.Type(types.Typ[types.Float32], llssa.InGo))
case llgoBitCastTo64F:
ret = b.BitCast(p.compileValue(b, args[0]), b.Prog.Float64())
default:
panic("todo")
}
@@ -650,6 +740,12 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
return ret
}
func (p *context) jumpTo(v *ssa.Jump) llssa.BasicBlock {
fn := p.fn
succs := v.Block().Succs
return fn.Block(succs[0].Index)
}
func (p *context) compileInstr(b llssa.Builder, instr ssa.Instruction) {
if iv, ok := instr.(instrOrValue); ok {
p.compileInstrOrValue(b, iv, false)
@@ -673,9 +769,7 @@ func (p *context) compileInstr(b llssa.Builder, instr ssa.Instruction) {
val := p.compileValue(b, v.Val)
b.Store(ptr, val)
case *ssa.Jump:
fn := p.fn
succs := v.Block().Succs
jmpb := fn.Block(succs[0].Index)
jmpb := p.jumpTo(v)
b.Jump(jmpb)
case *ssa.Return:
var results []llssa.Expr
@@ -706,12 +800,13 @@ func (p *context) compileInstr(b llssa.Builder, instr ssa.Instruction) {
}
}
func (p *context) compileFunction(v *ssa.Function) (llssa.Function, int) {
func (p *context) compileFunction(v *ssa.Function) (goFn llssa.Function, pyFn llssa.PyObjRef, kind int) {
// v.Pkg == nil: means auto generated function?
if v.Pkg == p.goPkg || v.Pkg == nil {
// function in this package
if fn := p.compileFuncDecl(p.pkg, v); fn != nil {
return fn, goFunc
goFn, pyFn, kind = p.compileFuncDecl(p.pkg, v)
if kind != ignoredFunc {
return
}
}
return p.funcOf(v)
@@ -730,11 +825,13 @@ func (p *context) compileValue(b llssa.Builder, v ssa.Value) llssa.Expr {
}
}
case *ssa.Function:
fn, _ := p.compileFunction(v)
return fn.Expr
aFn, pyFn, _ := p.compileFunction(v)
if aFn != nil {
return aFn.Expr
}
return pyFn.Expr
case *ssa.Global:
g := p.varOf(v)
return g.Expr
return p.varOf(b, v)
case *ssa.Const:
t := types.Default(v.Type())
return b.Const(v.Value, p.prog.Type(t, llssa.InGo))
@@ -814,6 +911,7 @@ func NewPackage(prog llssa.Program, pkg *ssa.Package, files []*ast.File) (ret ll
types.Unsafe: {kind: PkgDeclOnly}, // TODO(xsw): PkgNoInit or PkgDeclOnly?
},
}
ctx.initPyModule()
ctx.initFiles(pkgPath, files)
for _, m := range members {
member := m.val

View File

@@ -28,8 +28,12 @@ func testCompile(t *testing.T, src, expected string) {
cltest.TestCompileEx(t, src, "foo.go", expected)
}
func TestFromTestpy(t *testing.T) {
cltest.FromDir(t, "", "./_testpy", false)
}
func TestFromTestlibc(t *testing.T) {
cltest.FromDir(t, "", "./_testlibc", false)
cltest.FromDir(t, "", "./_testlibc", true)
}
func TestFromTestrt(t *testing.T) {
@@ -41,7 +45,15 @@ func TestFromTestdata(t *testing.T) {
}
func TestSqlite(t *testing.T) {
cltest.Pkg(t, "github.com/goplus/llgo/x/sqlite", "../x/sqlite/sqlite.ll")
cltest.Pkg(t, "github.com/goplus/llgo/x/sqlite", "../x/sqlite/llgo_autogen.ll")
}
func TestFromTestpymath(t *testing.T) {
cltest.Pkg(t, ssa.PkgPython+"/math", "../py/math/llgo_autogen.ll")
}
func TestPython(t *testing.T) {
cltest.Pkg(t, ssa.PkgPython, "../py/llgo_autogen.ll")
}
func TestRuntime(t *testing.T) {

View File

@@ -30,6 +30,8 @@ import (
"golang.org/x/tools/go/ssa"
)
// -----------------------------------------------------------------------------
type symInfo struct {
file string
fullName string
@@ -101,6 +103,8 @@ func pkgKind(v string) (int, string) {
// return PkgLinkBitCode
if strings.HasPrefix(v, "link:") { // "link: <libpath>"
return PkgLinkExtern, v[5:]
} else if strings.HasPrefix(v, "py.") { // "py.<module>"
return PkgPyModule, v[3:]
}
}
return PkgLLGo, ""
@@ -210,7 +214,7 @@ func (p *context) initLink(line string, prefix int, f func(inPkgName string) (fu
} else {
panic(line + ": no specified call convention. eg. //go:linkname Printf C.printf")
}
} else {
} else if c := inPkgName[0]; c >= 'A' && c <= 'Z' {
fmt.Fprintln(os.Stderr, "==>", line)
fmt.Fprintf(os.Stderr, "llgo: linkname %s not found and ignored\n", inPkgName)
}
@@ -303,17 +307,18 @@ const (
ignoredFunc = iota
goFunc = int(llssa.InGo)
cFunc = int(llssa.InC)
pyFunc = int(llssa.InPython)
llgoInstr = -1
llgoInstrBase = 0x80
llgoUnreachable = llgoInstrBase + 0
llgoCstr = llgoInstrBase + 1
llgoAlloca = llgoInstrBase + 2
llgoAllocaCStr = llgoInstrBase + 3
llgoAdvance = llgoInstrBase + 4
llgoIndex = llgoInstrBase + 5
llgoBitCastTo32F = llgoInstrBase + 6
llgoBitCastTo64F = llgoInstrBase + 7
llgoInstrBase = 0x80
llgoUnreachable = llgoInstrBase + 0
llgoCstr = llgoInstrBase + 1
llgoAlloca = llgoInstrBase + 2
llgoAllocaCStr = llgoInstrBase + 3
llgoAdvance = llgoInstrBase + 4
llgoIndex = llgoInstrBase + 5
llgoStringData = llgoInstrBase + 6
llgoPyList = llgoInstrBase + 7
)
func (p *context) funcName(fn *ssa.Function, ignore bool) (*types.Package, string, int) {
@@ -339,6 +344,9 @@ func (p *context) funcName(fn *ssa.Function, ignore bool) (*types.Package, strin
if strings.HasPrefix(v, "C.") {
return nil, v[2:], cFunc
}
if strings.HasPrefix(v, "py.") {
return pkg, v[3:], pyFunc
}
if strings.HasPrefix(v, "llgo.") {
return nil, v[5:], llgoInstr
}
@@ -351,24 +359,35 @@ const (
ignoredVar = iota
goVar = int(llssa.InGo)
cVar = int(llssa.InC)
pyVar = int(llssa.InPython)
)
func (p *context) varName(pkg *types.Package, v *ssa.Global) (vName string, vtype int) {
name := llssa.FullName(pkg, v.Name())
if v, ok := p.link[name]; ok {
if strings.HasPrefix(v, "py.") {
return v[3:], pyVar
}
return v, cVar
}
return name, goVar
}
func (p *context) varOf(v *ssa.Global) (ret llssa.Global) {
func (p *context) varOf(b llssa.Builder, v *ssa.Global) llssa.Expr {
pkgTypes := p.ensureLoaded(v.Pkg.Pkg)
pkg := p.pkg
name, vtype := p.varName(pkgTypes, v)
if ret = pkg.VarOf(name); ret == nil {
if vtype == pyVar {
if kind, mod := pkgKindByScope(pkgTypes.Scope()); kind == PkgPyModule {
return b.PyNewVar(pysymPrefix+mod, name).Expr
}
panic("unreachable")
}
ret := pkg.VarOf(name)
if ret == nil {
ret = pkg.NewVar(name, v.Type(), llssa.Background(vtype))
}
return
return ret.Expr
}
func (p *context) ensureLoaded(pkgTypes *types.Package) *types.Package {
@@ -391,3 +410,17 @@ func pkgKindByPath(pkgPath string) int {
}
return PkgNormal
}
// -----------------------------------------------------------------------------
const (
pysymPrefix = "__llgo_py."
)
func (p *context) initPyModule() {
if kind, mod := pkgKindByScope(p.goTyps.Scope()); kind == PkgPyModule {
p.pyMod = mod
}
}
// -----------------------------------------------------------------------------

2
go.mod
View File

@@ -18,3 +18,5 @@ require (
golang.org/x/mod v0.17.0 // indirect
golang.org/x/sync v0.7.0 // indirect
)
retract v0.8.0

View File

@@ -29,7 +29,7 @@ import (
"time"
wasm "github.com/aykevl/go-wasm"
"github.com/goplus/llgo/x/ar"
"github.com/goplus/llgo/xtool/ar"
)
// Create creates an arcive for static linking from a list of object files

View File

@@ -33,7 +33,7 @@ import (
"golang.org/x/tools/go/ssa"
"github.com/goplus/llgo/cl"
"github.com/goplus/llgo/x/clang"
"github.com/goplus/llgo/xtool/clang"
llssa "github.com/goplus/llgo/ssa"
)
@@ -120,18 +120,31 @@ func Do(args []string, conf *Config) {
cl.SetDebug(cl.DbgFlagAll)
}
var needRt bool
var rt []*packages.Package
prog := llssa.NewProgram(nil)
load := func() []*packages.Package {
if rt == nil {
var err error
rt, err = packages.Load(cfg, llssa.PkgRuntime, llssa.PkgPython)
check(err)
}
return rt
}
prog.SetRuntime(func() *types.Package {
rt, err = packages.Load(cfg, llssa.PkgRuntime)
check(err)
needRt = true
rt := load()
return rt[0].Types
})
prog.SetPython(func() *types.Package {
rt := load()
return rt[1].Types
})
pkgs := buildAllPkgs(prog, initial, mode, verbose)
var runtimeFiles []string
if rt != nil {
if needRt {
runtimeFiles = allLinkFiles(rt)
}
if mode != ModeBuild {
@@ -147,12 +160,22 @@ func Do(args []string, conf *Config) {
}
}
func setNeedRuntime(pkg *packages.Package) {
pkg.ID = "" // just use pkg.Module to mark it needs runtime
func setNeedRuntimeOrPyInit(pkg *packages.Package, needRuntime, needPyInit bool) {
v := []byte{'0', '0'}
if needRuntime {
v[0] = '1'
}
if needPyInit {
v[1] = '1'
}
pkg.ID = string(v) // just use pkg.ID to mark it needs runtime
}
func isNeedRuntime(pkg *packages.Package) bool {
return pkg.ID == ""
func isNeedRuntimeOrPyInit(pkg *packages.Package) (needRuntime, needPyInit bool) {
if len(pkg.ID) == 2 {
return pkg.ID[0] == '1', pkg.ID[1] == '1'
}
return
}
func buildAllPkgs(prog llssa.Program, initial []*packages.Package, mode Mode, verbose bool) (pkgs []*aPackage) {
@@ -172,28 +195,31 @@ func buildAllPkgs(prog llssa.Program, initial []*packages.Package, mode Mode, ve
// skip packages that only contain declarations
// and set no export file
pkg.ExportFile = ""
case cl.PkgLinkIR:
// skip packages that don't need to be compiled but need to be linked
case cl.PkgLinkIR, cl.PkgLinkExtern, cl.PkgPyModule:
pkgPath := pkg.PkgPath
if isPkgInLLGo(pkgPath) {
pkg.ExportFile = concatPkgLinkFiles(pkgPath)
} else {
panic("todo")
// panic("todo")
// TODO(xsw): support packages out of llgo
pkg.ExportFile = ""
}
case cl.PkgLinkExtern:
// skip packages that don't need to be compiled but need to be linked with external library
linkFile := os.ExpandEnv(strings.TrimSpace(param))
dir, lib := filepath.Split(linkFile)
command := " -l " + lib
if dir != "" {
command += " -L " + dir
if kind == cl.PkgLinkExtern { // need to be linked with external library
linkFile := os.ExpandEnv(strings.TrimSpace(param))
dir, lib := filepath.Split(linkFile)
command := " -l " + lib
if dir != "" {
command += " -L " + dir
}
if isSingleLinkFile(pkg.ExportFile) {
pkg.ExportFile = command + " " + pkg.ExportFile
} else {
pkg.ExportFile = command + pkg.ExportFile
}
}
pkg.ExportFile = command
default:
buildPkg(prog, aPkg, mode, verbose)
if prog.NeedRuntime() {
setNeedRuntime(pkg)
}
setNeedRuntimeOrPyInit(pkg, prog.NeedRuntime, prog.NeedPyInit)
}
}
return
@@ -212,27 +238,43 @@ func linkMainPkg(pkg *packages.Package, pkgs []*aPackage, runtimeFiles []string,
args[1] = app
args[2] = "-Wno-override-module"
needRuntime := false
needPyInit := false
packages.Visit([]*packages.Package{pkg}, nil, func(p *packages.Package) {
if p.ExportFile != "" && !isRuntimePkg(p.PkgPath) { // skip packages that only contain declarations
args = appendLinkFiles(args, p.ExportFile)
need1, need2 := isNeedRuntimeOrPyInit(p)
if !needRuntime {
needRuntime = isNeedRuntime(p)
needRuntime = need1
}
if !needPyInit {
needPyInit = need2
}
}
})
var aPkg *aPackage
for _, v := range pkgs {
if v.Package == pkg { // found this package
aPkg = v
break
}
}
dirty := false
if needRuntime && runtimeFiles != nil {
args = append(args, runtimeFiles...)
} else {
for _, aPkg := range pkgs {
if aPkg.Package == pkg { // make empty runtime.init if no runtime needed
lpkg := aPkg.LPkg
lpkg.FuncOf(cl.RuntimeInit).MakeBody(1).Return()
if needLLFile(mode) {
os.WriteFile(pkg.ExportFile, []byte(lpkg.String()), 0644)
}
break
}
}
dirty = true
fn := aPkg.LPkg.FuncOf(cl.RuntimeInit)
fn.MakeBody(1).Return()
}
if needPyInit {
dirty = aPkg.LPkg.PyInit()
}
if dirty && needLLFile(mode) {
lpkg := aPkg.LPkg
os.WriteFile(pkg.ExportFile, []byte(lpkg.String()), 0644)
}
if verbose || mode != ModeRun {
@@ -414,14 +456,14 @@ func llgoRoot() string {
}
func appendLinkFiles(args []string, file string) []string {
if isMultiLinkFiles(file) {
return append(args, strings.Split(file[1:], " ")...)
if isSingleLinkFile(file) {
return append(args, file)
}
return append(args, file)
return append(args, strings.Split(file[1:], " ")...)
}
func isMultiLinkFiles(ret string) bool {
return len(ret) > 0 && ret[0] == ' '
func isSingleLinkFile(ret string) bool {
return len(ret) > 0 && ret[0] != ' '
}
func concatPkgLinkFiles(pkgPath string) string {

View File

@@ -30,6 +30,7 @@ import (
"golang.org/x/tools/go/ssa/ssautil"
llssa "github.com/goplus/llgo/ssa"
cpackages "golang.org/x/tools/go/packages"
)
func Init() {
@@ -71,14 +72,17 @@ func Gen(pkgPath, inFile string, src any) string {
}
prog := llssa.NewProgram(nil)
prog.SetRuntime(func() *types.Package {
rt, err := imp.Import(llssa.PkgRuntime)
check(err)
return rt
initRtAndPy(prog, &cpackages.Config{
Mode: loadSyntax | cpackages.NeedDeps,
})
ret, err := cl.NewPackage(prog, ssaPkg, files)
check(err)
if prog.NeedPyInit { // call PyInit if needed
ret.PyInit()
}
return ret.String()
}

View File

@@ -38,6 +38,27 @@ const (
loadSyntax = loadTypes | packages.NeedSyntax | packages.NeedTypesInfo
)
func initRtAndPy(prog llssa.Program, cfg *packages.Config) {
var pkgRtAndPy []*packages.Package
load := func() []*packages.Package {
if pkgRtAndPy == nil {
var err error
pkgRtAndPy, err = packages.Load(cfg, llssa.PkgRuntime, llssa.PkgPython)
check(err)
}
return pkgRtAndPy
}
prog.SetRuntime(func() *types.Package {
rt := load()
return rt[0].Types
})
prog.SetPython(func() *types.Package {
rt := load()
return rt[1].Types
})
}
func GenFrom(fileOrPkg string) string {
cfg := &packages.Config{
Mode: loadSyntax | packages.NeedDeps,
@@ -52,11 +73,7 @@ func GenFrom(fileOrPkg string) string {
ssaPkg.Build()
prog := llssa.NewProgram(nil)
prog.SetRuntime(func() *types.Package {
rt, err := packages.Load(cfg, llssa.PkgRuntime)
check(err)
return rt[0].Types
})
initRtAndPy(prog, cfg)
if Verbose {
ssaPkg.WriteTo(os.Stderr)
@@ -65,6 +82,10 @@ func GenFrom(fileOrPkg string) string {
ret, err := cl.NewPackage(prog, ssaPkg, pkg.Syntax)
check(err)
if prog.NeedPyInit { // call PyInit if needed
ret.PyInit()
}
return ret.String()
}
@@ -82,8 +103,6 @@ func SmartDoFile(inFile string, pkgPath ...string) {
fname := autgenFile
if inCompilerDir(absDir) {
fname = "out.ll"
} else if inSqlite(absDir) {
fname = "sqlite.ll"
}
outFile := dir + fname
@@ -108,7 +127,3 @@ func genZip(dir string, outFile, inFile string) {
func inCompilerDir(dir string) bool {
return strings.Contains(dir, "/llgo/cl/")
}
func inSqlite(dir string) bool {
return strings.HasSuffix(dir, "/llgo/x/sqlite")
}

Binary file not shown.

40
internal/runtime/slice.go Normal file
View File

@@ -0,0 +1,40 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package runtime
// nextslicecap computes the next appropriate slice length.
func nextslicecap(newLen, oldCap int) int {
newcap := oldCap
doublecap := newcap + newcap
if newLen > doublecap {
return newLen
}
const threshold = 256
if oldCap < threshold {
return doublecap
}
for {
// Transition from growing 2x for small slices
// to growing 1.25x for large slices. This formula
// gives a smooth-ish transition between the two.
newcap += (newcap + 3*threshold) >> 2
// We need to check `newcap >= newLen` and whether `newcap` overflowed.
// newLen is guaranteed to be larger than zero, hence
// when newcap overflows then `uint(newcap) > uint(newLen)`.
// This allows to check for both with the same comparison.
if uint(newcap) >= uint(newLen) {
break
}
}
// Set newcap to the requested cap when
// the newcap calculation overflowed.
if newcap <= 0 {
return newLen
}
return newcap
}

View File

@@ -77,38 +77,18 @@ func CheckI2Int(v Interface, t *Type) (uintptr, bool) {
return 0, false
}
func I2Float64(v Interface, t *Type) float64 {
func I2String(v Interface, t *Type) string {
if v.tab._type == t {
return bitCastTo64F(uint64(uintptr(v.data)))
return *(*string)(v.data)
}
panic("I2Float64: type mismatch")
panic("I2String: type mismatch")
}
func CheckI2Float64(v Interface, t *Type) (float64, bool) {
func CheckI2String(v Interface, t *Type) (string, bool) {
if v.tab._type == t {
return bitCastTo64F(uint64(uintptr(v.data))), true
return *(*string)(v.data), true
}
return 0, false
return "", false
}
func I2Float32(v Interface, t *Type) float32 {
if v.tab._type == t {
return bitCastTo32F(uint32(uintptr(v.data)))
}
panic("I2Float32: type mismatch")
}
func CheckI2Float32(v Interface, t *Type) (float32, bool) {
if v.tab._type == t {
return bitCastTo32F(uint32(uintptr(v.data))), true
}
return 0, false
}
//go:linkname bitCastTo64F llgo.bitCastTo64F
func bitCastTo64F(uint64) float64
//go:linkname bitCastTo32F llgo.bitCastTo32F
func bitCastTo32F(uint32) float32
// -----------------------------------------------------------------------------

View File

@@ -70,4 +70,25 @@ func SliceData(s Slice) unsafe.Pointer {
return s.data
}
// SliceAppend append elem data and returns a slice.
func SliceAppend(src Slice, data unsafe.Pointer, num, etSize int) Slice {
if etSize == 0 {
return src
}
oldLen := src.len
newLen := src.len + num
if newLen > src.cap {
newCap := nextslicecap(newLen, src.cap)
p := AllocZ(uintptr(newCap * etSize))
if oldLen != 0 {
c.Memcpy(p, src.data, uintptr(oldLen*etSize))
}
src.data = p
src.cap = newCap
}
src.len = newLen
c.Memcpy(c.Advance(src.data, oldLen*etSize), data, uintptr(num*etSize))
return src
}
// -----------------------------------------------------------------------------

View File

@@ -45,16 +45,6 @@ func NewString(data unsafe.Pointer, len int) String {
return String{data, len}
}
// StringLen returns the length of a string.
func StringLen(s String) int {
return s.len
}
// StringData returns the data pointer of a string.
func StringData(s String) unsafe.Pointer {
return s.data
}
// StringCat concatenates two strings.
func StringCat(a, b String) String {
n := a.len + b.len

33
py/README.md Normal file
View File

@@ -0,0 +1,33 @@
Linking Python to Go
=====
TODO
## Demo
The `_demo` directory contains our demos (it start with `_` to prevent the `go` command from compiling it):
* [hellopy](_demo/hellopy/hello.go): link Python to Go and say `Hello world`
* [clpy](_demo/clpy/cleval.go): compile Python code and eval.
* [callpy](_demo/callpy/call.go): call Python standard library function `math.sqrt`.
### How to run demos
To run the demos in directory `_demo`, you need to set the `LLGO_LIB_PYTHON` environment variable first. Assuming you use Python 3.12, and the `libpython3.12.so` (or `libpython3.12.dylib` or `python3.12.lib`) file is in the /foo/bar directory, then you need to set `LLGO_LIB_PYTHON` to:
```sh
export LLGO_LIB_PYTHON=/foo/bar/python3.12
```
For example, `/opt/homebrew/Frameworks/Python.framework/Versions/3.12/libpython3.12.dylib` is a typical python lib location under macOS. So we should set it like this:
```sh
export LLGO_LIB_PYTHON=/opt/homebrew/Frameworks/Python.framework/Versions/3.12/python3.12
```
Then you can run the demos in directory `_demo`:
```sh
cd <demo-directory> # eg. cd _demo/hellopy
llgo run .
```

19
py/_demo/callpy/call.go Normal file
View File

@@ -0,0 +1,19 @@
package main
import (
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/py"
)
func main() {
py.Initialize()
py.SetProgramName(*c.Argv)
math := py.ImportModule(c.Str("math"))
sqrt := math.GetAttrString(c.Str("sqrt"))
sqrt2 := sqrt.CallOneArg(py.Float(2))
c.Printf(c.Str("sqrt(2) = %f\n"), sqrt2.Float64())
sqrt2.DecRef()
sqrt.DecRef()
math.DecRef()
py.Finalize()
}

23
py/_demo/clpy/cleval.go Normal file
View File

@@ -0,0 +1,23 @@
package main
import (
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/py"
)
func main() {
py.Initialize()
py.SetProgramName(*c.Argv)
code := py.CompileString(c.Str(`print('Hello, World!')`), c.Str(`hello.py`), py.EvalInput)
if code != nil {
mod := py.ImportModule(c.Str("__main__"))
gbl := mod.ModuleGetDict()
result := py.EvalCode(code, gbl, nil)
result.DecRef()
mod.DecRef()
code.DecRef()
}
py.Finalize()
}

13
py/_demo/hellopy/hello.go Normal file
View File

@@ -0,0 +1,13 @@
package main
import (
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/py"
)
func main() {
py.Initialize()
py.SetProgramName(*c.Argv)
py.RunSimpleString(c.Str(`print('Hello, World!')`))
py.Finalize()
}

49
py/_pyg/llpyg/llpyg.c Normal file
View File

@@ -0,0 +1,49 @@
#include <stdlib.h>
#include <stdio.h>
typedef struct PyObject PyObject;
void Py_Initialize();
PyObject* PyImport_ImportModule(const char* modName);
PyObject* PyModule_GetDict(PyObject* mod);
PyObject* PyObject_Str(PyObject* obj);
PyObject* PyDict_Keys(PyObject* dict);
PyObject* PyList_GetItem(PyObject* list, size_t index);
PyObject* PyTuple_GetItem(PyObject* tuple, size_t index);
PyObject* PyObject_GetAttr(PyObject* mod, PyObject* attrName);
PyObject* PyObject_GetAttrString(PyObject* mod, const char* attrName);
PyObject* PyObject_CallOneArg(PyObject* fn, PyObject* arg);
const char* PyUnicode_AsUTF8(PyObject* str);
size_t PyList_Size(PyObject* list);
int PyCallable_Check(PyObject*);
int main() {
Py_Initialize();
PyObject* inspect = PyImport_ImportModule("inspect");
PyObject* signature = PyObject_GetAttrString(inspect, "signature");
PyObject* mod = PyImport_ImportModule("numpy");
PyObject* dict = PyModule_GetDict(mod);
PyObject* keys = PyDict_Keys(dict);
size_t i, n;
n = PyList_Size(keys);
for (i = 0; i < n; i++) {
PyObject* key = PyList_GetItem(keys, i);
PyObject* val = PyObject_GetAttr(mod, key);
if (PyCallable_Check(val) != 0) {
PyObject* doc = PyObject_GetAttrString(val, "__doc__");
PyObject* sig = PyObject_CallOneArg(signature, val);
printf("-----------------------------------\n");
printf("sig: %p\n", sig);
printf("%s: %s\n", PyUnicode_AsUTF8(key), PyUnicode_AsUTF8(PyObject_Str(sig)));
printf("%s\n", PyUnicode_AsUTF8(key));
if (doc != NULL) {
printf("%s\n", PyUnicode_AsUTF8(doc));
}
}
}
return 0;
}

53
py/_pyg/module.c Normal file
View File

@@ -0,0 +1,53 @@
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
// example:
// llgoLoadPyModSyms(mod, "name1", &func1, "name2", &func2, NULL)
typedef struct PyObject PyObject;
PyObject* PyObject_GetAttrString(PyObject* mod, const char* attrName);
void llgoLoadPyModSyms(PyObject* mod, ...) {
va_list ap;
va_start(ap, mod);
for (;;) {
const char* name = va_arg(ap, const char*);
if (name == NULL) {
break;
}
PyObject** pfunc = va_arg(ap, PyObject**);
if (*pfunc == NULL) {
*pfunc = PyObject_GetAttrString(mod, name);
}
}
va_end(ap);
}
/*
wchar_t* toWcs(const char* str) {
size_t len = mbstowcs(NULL, str, 0);
wchar_t* wstr = (wchar_t*)malloc((len + 1) * sizeof(wchar_t));
mbstowcs(wstr, str, len + 1);
return wstr;
}
char* toMbs(const wchar_t* str) {
size_t len = wcstombs(NULL, str, 0);
char* mstr = (char*)malloc(len + 1);
wcstombs(mstr, str, len + 1);
return mstr;
}
wchar_t *Py_GetPath();
void Py_SetPath(const wchar_t* path);
void Py_Initialize();
void llgoPyInitialize() {
setenv("PYTHONPATH", "/opt/homebrew/lib/python3.12/site-packages", 1);
Py_Initialize();
printf("sys.path = %s\n", toMbs(Py_GetPath()));
}
*/

33
py/arg.go Normal file
View File

@@ -0,0 +1,33 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package py
import (
_ "unsafe"
"github.com/goplus/llgo/c"
)
// https://docs.python.org/3/c-api/arg.html
// Create a new value based on a format string similar to those accepted by the
// PyArg_Parse* family of functions and a sequence of values. Returns the value or
// nil in the case of an error; an exception will be raised if nil is returned.
// See https://docs.python.org/3/c-api/arg.html#c.Py_BuildValue
//
//go:linkname BuildValue C.Py_BuildValue
func BuildValue(format *c.Char, __llgo_va_list ...any) *Object

61
py/builtins/builtins.go Normal file
View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package builtins
import (
_ "unsafe"
"github.com/goplus/llgo/py"
)
const (
LLGoPackage = "py.inspect"
)
// https://docs.python.org/3/library/functions.html
// https://docs.python.org/3/library/constants.html
// print(*objects, sep=' ', end='\n', file=None, flush=False)
//
// Print objects to the text stream file, separated by sep and followed by
// end. sep, end, file, and flush, if present, must be given as keyword
// arguments.
//
// All non-keyword arguments are converted to strings like str() does and
// written to the stream, separated by sep and followed by end. Both sep
// and end must be strings; they can also be None, which means to use the
// default values. If no objects are given, print() will just write end.
//
//go:linkname Print py.print
func Print(objects ...*py.Object)
//go:linkname PrintEx py.print
func PrintEx(__llgo_kwargs *py.Object, objects ...*py.Object)
// Invoke the built-in help system. (This function is intended for interactive
// use.) If no argument is given, the interactive help system starts on the
// interpreter console. If the argument is a string, then the string is looked
// up as the name of a module, function, class, method, keyword, or documentation
// topic, and a help page is printed on the console. If the argument is any other
// kind of object, a help page on the object is generated.
//
// Note that if a slash(/) appears in the parameter list of a function when invoking
// help(), it means that the parameters prior to the slash are positional-only. For
// more info, see the FAQ entry on positional-only parameters.
//
//go:linkname Help py.help
func Help(object *py.Object)

Binary file not shown.

50
py/bytes.go Normal file
View File

@@ -0,0 +1,50 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package py
/*
import (
_ "unsafe"
"github.com/goplus/llgo/c"
)
// https://docs.python.org/3/c-api/bytes.html
// String returns a new bytes object from a C string.
//
//go:linkname FromCStr C.PyBytes_FromString
func FromCStr(s *c.Char) *Object
// FromString returns a new bytes object from a Go string.
func FromString(s string) *Object {
return stringFromStringAndSize(c.GoStringData(s), uintptr(len(s)))
}
//go:linkname stringFromStringAndSize C.PyBytes_FromStringAndSize
func stringFromStringAndSize(s *c.Char, size uintptr) *Object
// CStr returns the content of a bytes object as a C string.
//
// llgo:link (*Object).CStr C.PyBytes_AsString
func (o *Object) CStr() *c.Char { return nil }
// llgo:link (*Object).Strlen C.PyBytes_Size
func (o *Object) Strlen() uintptr { return 0 }
*/

131
py/call.go Normal file
View File

@@ -0,0 +1,131 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package py
import (
_ "unsafe"
"github.com/goplus/llgo/c"
)
// https://docs.python.org/3/c-api/call.html
// Determine if the object o is callable. Return 1 if the object is callable and
// 0 otherwise. This function always succeeds.
//
// llgo:link (*Object).Callable C.PyCallable_Check
func (o *Object) Callable() c.Int { return 0 }
// Call a callable Python object o, with arguments given by the tuple args, and
// named arguments given by the dictionary kwargs.
//
// args must not be nil; use an empty tuple if no arguments are needed. If no named
// arguments are needed, kwargs can be nil.
//
// Return the result of the call on success, or raise an exception and return nil
// on failure.
//
// This is the equivalent of the Python expression: o(*args, **kwargs).
//
// llgo:link (*Object).Call C.PyObject_Call
func (o *Object) Call(args, kwargs *Object) *Object { return nil }
// Call a callable Python object callable without any arguments. It is the most
// efficient way to call a callable Python object without any argument.
//
// Return the result of the call on success, or raise an exception and return nil
// on failure.
//
// llgo:link (*Object).CallNoArgs C.PyObject_CallNoArgs
func (o *Object) CallNoArgs() *Object { return nil }
// Call a callable Python object callable with exactly 1 positional argument arg
// and no keyword arguments.
//
// Return the result of the call on success, or raise an exception and return nil
// on failure.
//
// llgo:link (*Object).CallOneArg C.PyObject_CallOneArg
func (o *Object) CallOneArg(arg *Object) *Object { return nil }
// Call a callable Python object o, with arguments given by the tuple args. If no
// arguments are needed, then args can be nil.
//
// Return the result of the call on success, or raise an exception and return nil
// on failure.
//
// This is the equivalent of the Python expression: o(*args).
//
// llgo:link (*Object).CallObject C.PyObject_CallObject
func (o *Object) CallObject(args *Object) *Object { return nil }
// Call a callable Python object o, with a variable number of C arguments. The C
// arguments are described using a py.BuildValue style format string. The format
// can be nil, indicating that no arguments are provided.
//
// Return the result of the call on success, or raise an exception and return nil
// on failure.
//
// This is the equivalent of the Python expression: o(*args).
//
// Note that if you only pass PyObject* args, (*Object).CallFunctionObjArgs is a
// faster alternative.
//
// llgo:link (*Object).CallFunction C.PyObject_CallFunction
func (o *Object) CallFunction(format *c.Char, __llgo_va_list ...any) *Object { return nil }
// Call a callable Python object o, with a variable number of PyObject* arguments.
// The arguments are provided as a variable number of parameters followed by nil.
//
// Return the result of the call on success, or raise an exception and return nil
// on failure.
//
// This is the equivalent of the Python expression: o(arg1, arg2, ...).
//
// llgo:link (*Object).CallFunctionObjArgs C.PyObject_CallFunctionObjArgs
func (o *Object) CallFunctionObjArgs(__llgo_va_list ...any) *Object { return nil }
// llgo:link (*Object).CallMethod C.PyObject_CallMethod
func (o *Object) CallMethod(name *c.Char, format *c.Char, __llgo_va_list ...any) *Object {
return nil
}
// llgo:link (*Object).CallMethodObjArgs C.PyObject_CallMethodObjArgs
func (o *Object) CallMethodObjArgs(name *Object, __llgo_va_list ...any) *Object { return nil }
// llgo:link (*Object).CallMethodNoArgs C.PyObject_CallMethodNoArgs
func (o *Object) CallMethodNoArgs(name *Object) *Object { return nil }
// llgo:link (*Object).CallMethodOneArg C.PyObject_CallMethodOneArg
func (o *Object) CallMethodOneArg(name, arg *Object) *Object { return nil }
// llgo:link (*Object).Vectorcall C.PyObject_Vectorcall
func (o *Object) Vectorcall(args **Object, nargs uintptr, kwnames *Object) *Object {
return nil
}
// llgo:link (*Object).VectorcallDict C.PyObject_VectorcallDict
func (o *Object) VectorcallDict(args **Object, nargs uintptr, kwdict *Object) *Object {
return nil
}
// llgo:link (*Object).VectorcallMethod C.PyObject_VectorcallMethod
func (o *Object) VectorcallMethod(name *Object, args **Object, nargs uintptr, kwnames *Object) *Object {
return nil
}
// -----------------------------------------------------------------------------

41
py/code.go Normal file
View File

@@ -0,0 +1,41 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package py
import (
_ "unsafe"
)
// https://docs.python.org/3/c-api/code.html
// Equivalent to the Python code getattr(co, 'co_code'). Returns a strong
// reference to a BytesObject representing the bytecode in a code object.
// On error, nil is returned and an exception is raised.
//
// This BytesObject may be created on-demand by the interpreter and does
// not necessarily represent the bytecode actually executed by CPython.
// The primary use case for this function is debuggers and profilers.
//
// llgo:link (*Object).CodeBytes C.PyCode_GetCode
func (o *Object) CodeBytes() *Object { return nil }
// Equivalent to the Python code getattr(co, 'co_varnames'). Returns a new
// reference to a TupleObject containing the names of the local variables.
// On error, nil is returned and an exception is raised.
//
// llgo:link (*Object).CodeVarnames C.PyCode_GetVarnames
func (o *Object) CodeVarnames() *Object { return nil }

45
py/dict.go Normal file
View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package py
import (
_ "unsafe"
)
// https://docs.python.org/3/c-api/dict.html
// Return a new empty dictionary, or nil on failure.
//
//go:linkname NewDict C.PyDict_New
func NewDict() *Object
// Return a ListObject containing all the keys from the dictionary.
//
// llgo:link (*Object).DictKeys C.PyDict_Keys
func (d *Object) DictKeys() *Object { return nil }
// Return a ListObject containing all the values from the dictionary.
//
// llgo:link (*Object).DictValues C.PyDict_Values
func (d *Object) DictValues() *Object { return nil }
// Return a ListObject containing all the items from the dictionary.
//
// llgo:link (*Object).DictItems C.PyDict_Items
func (d *Object) DictItems() *Object { return nil }
// -----------------------------------------------------------------------------

32
py/exceptions.go Normal file
View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package py
import (
_ "unsafe"
)
// https://docs.python.org/3/c-api/exceptions.html
// Clear the error indicator. If the error indicator is not set, there is
// no effect.
//
//go:linkname ErrClear C.PyErr_Clear
func ErrClear()
//go:linkname ErrPrint C.PyErr_Print
func ErrPrint()

32
py/float.go Normal file
View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package py
import (
_ "unsafe"
)
// https://docs.python.org/3/c-api/float.html
//go:linkname Float C.PyFloat_FromDouble
func Float(v float64) *Object
//go:linkname FloatFromSring C.PyFloat_FromString
func FloatFromSring(v *Object) *Object
// llgo:link (*Object).Float64 C.PyFloat_AsDouble
func (o *Object) Float64() float64 { return 0 }

56
py/func.go Normal file
View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package py
import (
_ "unsafe"
)
// https://docs.python.org/3/c-api/function.html
// Return a new function object associated with the code object code.
// globals must be a dictionary with the global variables accessible
// to the function.
//
// The functions docstring and name are retrieved from the code object.
// __module__ is retrieved from globals. The argument defaults, annotations
// and closure are set to nil. __qualname__ is set to the same value as
// the code objects co_qualname field.
//
//go:linkname NewFunc C.PyFunction_New
func NewFunc(code, globals *Object) *Object
// As NewFunc, but also allows setting the function objects __qualname__
// attribute. qualname should be a unicode object or nil; if nil, the
// __qualname__ attribute is set to the same value as the code objects
// co_qualname field.
//
//go:linkname NewFuncWithQualName C.PyFunction_NewWithQualName
func NewFuncWithQualName(code, globals, qualname *Object) *Object
/*
// Return true if o is a function object (has type PyFunction_Type). The
// parameter must not be nil. This function always succeeds.
//
// llgo:link (*Object).FuncCheck C.PyFunction_Check
func (o *Object) FuncCheck() c.Int { return 0 }
*/
// Return the code object associated with the function object op.
//
// llgo:link (*Object).FuncCode C.PyFunction_GetCode
func (f *Object) FuncCode() *Object { return nil }

14
py/inspect/doc.txt Normal file
View File

@@ -0,0 +1,14 @@
// https://docs.python.org/3/library/inspect.html
// Return a signature object for the given callable.
//
//go:linkname Signature py.signature
func Signature(callable *py.Object) *py.Object
// Get the names and default values of a Python functions parameters. A named
// tuple is returned:
//
// FullArgSpec(args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations)
//
//go:linkname Getfullargspec py.getfullargspec
func Getfullargspec(f *py.Object) *py.Object

617
py/inspect/gen.go Normal file
View File

@@ -0,0 +1,617 @@
package inspect
import (
_ "unsafe"
"github.com/goplus/llgo/py"
)
const LLGoPackage = "py.inspect"
// Compute the annotations dict for an object.
//
// obj may be a callable, class, or module.
// Passing in an object of any other type raises TypeError.
//
// Returns a dict. get_annotations() returns a new dict every time
// it's called; calling it twice on the same object will return two
// different but equivalent dicts.
//
// This function handles several details for you:
//
// * If eval_str is true, values of type str will
// be un-stringized using eval(). This is intended
// for use with stringized annotations
// ("from __future__ import annotations").
// * If obj doesn't have an annotations dict, returns an
// empty dict. (Functions and methods always have an
// annotations dict; classes, modules, and other types of
// callables may not.)
// * Ignores inherited annotations on classes. If a class
// doesn't have its own annotations dict, returns an empty dict.
// * All accesses to object members and dict values are done
// using getattr() and dict.get() for safety.
// * Always, always, always returns a freshly-created dict.
//
// eval_str controls whether or not values of type str are replaced
// with the result of calling eval() on those values:
//
// * If eval_str is true, eval() is called on values of type str.
// * If eval_str is false (the default), values of type str are unchanged.
//
// globals and locals are passed in to eval(); see the documentation
// for eval() for more information. If either globals or locals is
// None, this function may replace that value with a context-specific
// default, contingent on type(obj):
//
// * If obj is a module, globals defaults to obj.__dict__.
// * If obj is a class, globals defaults to
// sys.modules[obj.__module__].__dict__ and locals
// defaults to the obj class namespace.
// * If obj is a callable, globals defaults to obj.__globals__,
// although if obj is a wrapped function (using
// functools.update_wrapper()) it is first unwrapped.
//
//go:linkname GetAnnotations py.get_annotations
func GetAnnotations(obj *py.Object) *py.Object
// Return true if the object is a module.
//
//go:linkname Ismodule py.ismodule
func Ismodule(object *py.Object) *py.Object
// Return true if the object is a class.
//
//go:linkname Isclass py.isclass
func Isclass(object *py.Object) *py.Object
// Return true if the object is an instance method.
//
//go:linkname Ismethod py.ismethod
func Ismethod(object *py.Object) *py.Object
// Return true if the object is a method descriptor.
//
// But not if ismethod() or isclass() or isfunction() are true.
//
// This is new in Python 2.2, and, for example, is true of int.__add__.
// An object passing this test has a __get__ attribute but not a __set__
// attribute, but beyond that the set of attributes varies. __name__ is
// usually sensible, and __doc__ often is.
//
// Methods implemented via descriptors that also pass one of the other
// tests return false from the ismethoddescriptor() test, simply because
// the other tests promise more -- you can, e.g., count on having the
// __func__ attribute (etc) when an object passes ismethod().
//
//go:linkname Ismethoddescriptor py.ismethoddescriptor
func Ismethoddescriptor(object *py.Object) *py.Object
// Return true if the object is a data descriptor.
//
// Data descriptors have a __set__ or a __delete__ attribute. Examples are
// properties (defined in Python) and getsets and members (defined in C).
// Typically, data descriptors will also have __name__ and __doc__ attributes
// (properties, getsets, and members have both of these attributes), but this
// is not guaranteed.
//
//go:linkname Isdatadescriptor py.isdatadescriptor
func Isdatadescriptor(object *py.Object) *py.Object
// Return true if the object is a member descriptor.
//
// Member descriptors are specialized descriptors defined in extension
// modules.
//
//go:linkname Ismemberdescriptor py.ismemberdescriptor
func Ismemberdescriptor(object *py.Object) *py.Object
// Return true if the object is a getset descriptor.
//
// getset descriptors are specialized descriptors defined in extension
// modules.
//
//go:linkname Isgetsetdescriptor py.isgetsetdescriptor
func Isgetsetdescriptor(object *py.Object) *py.Object
// Return true if the object is a user-defined function.
//
// Function objects provide these attributes:
// __doc__ documentation string
// __name__ name with which this function was defined
// __code__ code object containing compiled function bytecode
// __defaults__ tuple of any default values for arguments
// __globals__ global namespace in which this function was defined
// __annotations__ dict of parameter annotations
// __kwdefaults__ dict of keyword only parameters with defaults
//
//go:linkname Isfunction py.isfunction
func Isfunction(object *py.Object) *py.Object
// Return true if the object is a user-defined generator function.
//
// Generator function objects provide the same attributes as functions.
// See help(isfunction) for a list of attributes.
//
//go:linkname Isgeneratorfunction py.isgeneratorfunction
func Isgeneratorfunction(obj *py.Object) *py.Object
// Decorator to ensure callable is recognised as a coroutine function.
//
//go:linkname Markcoroutinefunction py.markcoroutinefunction
func Markcoroutinefunction(func_ *py.Object) *py.Object
// Return true if the object is a coroutine function.
//
// Coroutine functions are normally defined with "async def" syntax, but may
// be marked via markcoroutinefunction.
//
//go:linkname Iscoroutinefunction py.iscoroutinefunction
func Iscoroutinefunction(obj *py.Object) *py.Object
// Return true if the object is an asynchronous generator function.
//
// Asynchronous generator functions are defined with "async def"
// syntax and have "yield" expressions in their body.
//
//go:linkname Isasyncgenfunction py.isasyncgenfunction
func Isasyncgenfunction(obj *py.Object) *py.Object
// Return true if the object is an asynchronous generator.
//
//go:linkname Isasyncgen py.isasyncgen
func Isasyncgen(object *py.Object) *py.Object
// Return true if the object is a generator.
//
// Generator objects provide these attributes:
// __iter__ defined to support iteration over container
// close raises a new GeneratorExit exception inside the
// generator to terminate the iteration
// gi_code code object
// gi_frame frame object or possibly None once the generator has
// been exhausted
// gi_running set to 1 when generator is executing, 0 otherwise
// next return the next item from the container
// send resumes the generator and "sends" a value that becomes
// the result of the current yield-expression
// throw used to raise an exception inside the generator
//
//go:linkname Isgenerator py.isgenerator
func Isgenerator(object *py.Object) *py.Object
// Return true if the object is a coroutine.
//
//go:linkname Iscoroutine py.iscoroutine
func Iscoroutine(object *py.Object) *py.Object
// Return true if object can be passed to an “await“ expression.
//
//go:linkname Isawaitable py.isawaitable
func Isawaitable(object *py.Object) *py.Object
// Return true if the object is a traceback.
//
// Traceback objects provide these attributes:
// tb_frame frame object at this level
// tb_lasti index of last attempted instruction in bytecode
// tb_lineno current line number in Python source code
// tb_next next inner traceback object (called by this level)
//
//go:linkname Istraceback py.istraceback
func Istraceback(object *py.Object) *py.Object
// Return true if the object is a frame object.
//
// Frame objects provide these attributes:
// f_back next outer frame object (this frame's caller)
// f_builtins built-in namespace seen by this frame
// f_code code object being executed in this frame
// f_globals global namespace seen by this frame
// f_lasti index of last attempted instruction in bytecode
// f_lineno current line number in Python source code
// f_locals local namespace seen by this frame
// f_trace tracing function for this frame, or None
//
//go:linkname Isframe py.isframe
func Isframe(object *py.Object) *py.Object
// Return true if the object is a code object.
//
// Code objects provide these attributes:
// co_argcount number of arguments (not including *, ** args
// or keyword only arguments)
// co_code string of raw compiled bytecode
// co_cellvars tuple of names of cell variables
// co_consts tuple of constants used in the bytecode
// co_filename name of file in which this code object was created
// co_firstlineno number of first line in Python source code
// co_flags bitmap: 1=optimized | 2=newlocals | 4=*arg | 8=**arg
// | 16=nested | 32=generator | 64=nofree | 128=coroutine
// | 256=iterable_coroutine | 512=async_generator
// co_freevars tuple of names of free variables
// co_posonlyargcount number of positional only arguments
// co_kwonlyargcount number of keyword only arguments (not including ** arg)
// co_lnotab encoded mapping of line numbers to bytecode indices
// co_name name with which this code object was defined
// co_names tuple of names other than arguments and function locals
// co_nlocals number of local variables
// co_stacksize virtual machine stack space required
// co_varnames tuple of names of arguments and local variables
//
//go:linkname Iscode py.iscode
func Iscode(object *py.Object) *py.Object
// Return true if the object is a built-in function or method.
//
// Built-in functions and methods provide these attributes:
// __doc__ documentation string
// __name__ original name of this function or method
// __self__ instance to which a method is bound, or None
//
//go:linkname Isbuiltin py.isbuiltin
func Isbuiltin(object *py.Object) *py.Object
// Return true if the object is a method wrapper.
//
//go:linkname Ismethodwrapper py.ismethodwrapper
func Ismethodwrapper(object *py.Object) *py.Object
// Return true if the object is any kind of function or method.
//
//go:linkname Isroutine py.isroutine
func Isroutine(object *py.Object) *py.Object
// Return true if the object is an abstract base class (ABC).
//
//go:linkname Isabstract py.isabstract
func Isabstract(object *py.Object) *py.Object
// Return all members of an object as (name, value) pairs sorted by name.
//
// Optionally, only return members that satisfy a given predicate.
//
//go:linkname Getmembers py.getmembers
func Getmembers(object *py.Object, predicate *py.Object) *py.Object
// Return all members of an object as (name, value) pairs sorted by name
//
// without triggering dynamic lookup via the descriptor protocol,
// __getattr__ or __getattribute__. Optionally, only return members that
// satisfy a given predicate.
//
// Note: this function may not be able to retrieve all members
// that getmembers can fetch (like dynamically created attributes)
// and may find members that getmembers can't (like descriptors
// that raise AttributeError). It can also return descriptor objects
// instead of instance members in some cases.
//
//go:linkname GetmembersStatic py.getmembers_static
func GetmembersStatic(object *py.Object, predicate *py.Object) *py.Object
// Return list of attribute-descriptor tuples.
//
// For each name in dir(cls), the return list contains a 4-tuple
// with these elements:
//
// 0. The name (a string).
//
// 1. The kind of attribute this is, one of these strings:
// 'class method' created via classmethod()
// 'static method' created via staticmethod()
// 'property' created via property()
// 'method' any other flavor of method or descriptor
// 'data' not a method
//
// 2. The class which defined this attribute (a class).
//
// 3. The object as obtained by calling getattr; if this fails, or if the
// resulting object does not live anywhere in the class' mro (including
// metaclasses) then the object is looked up in the defining class's
// dict (found by walking the mro).
//
// If one of the items in dir(cls) is stored in the metaclass it will now
// be discovered and not have None be listed as the class in which it was
// defined. Any items whose home class cannot be discovered are skipped.
//
//go:linkname ClassifyClassAttrs py.classify_class_attrs
func ClassifyClassAttrs(cls *py.Object) *py.Object
// Return tuple of base classes (including cls) in method resolution order.
//
//go:linkname Getmro py.getmro
func Getmro(cls *py.Object) *py.Object
// Get the object wrapped by *func*.
//
// Follows the chain of :attr:`__wrapped__` attributes returning the last
// object in the chain.
//
// *stop* is an optional callback accepting an object in the wrapper chain
// as its sole argument that allows the unwrapping to be terminated early if
// the callback returns a true value. If the callback never returns a true
// value, the last object in the chain is returned as usual. For example,
// :func:`signature` uses this to stop unwrapping if any object in the
// chain has a ``__signature__`` attribute defined.
//
// :exc:`ValueError` is raised if a cycle is encountered.
//
//go:linkname Unwrap py.unwrap
func Unwrap(func_ *py.Object) *py.Object
// Return the indent size, in spaces, at the start of a line of text.
//
//go:linkname Indentsize py.indentsize
func Indentsize(line *py.Object) *py.Object
// Get the documentation string for an object.
//
// All tabs are expanded to spaces. To clean up docstrings that are
// indented to line up with blocks of code, any whitespace than can be
// uniformly removed from the second line onwards is removed.
//
//go:linkname Getdoc py.getdoc
func Getdoc(object *py.Object) *py.Object
// Clean up indentation from docstrings.
//
// Any whitespace that can be uniformly removed from the second line
// onwards is removed.
//
//go:linkname Cleandoc py.cleandoc
func Cleandoc(doc *py.Object) *py.Object
// Work out which source or compiled file an object was defined in.
//
//go:linkname Getfile py.getfile
func Getfile(object *py.Object) *py.Object
// Return the module name for a given file, or None.
//
//go:linkname Getmodulename py.getmodulename
func Getmodulename(path *py.Object) *py.Object
// Return the filename that can be used to locate an object's source.
//
// Return None if no way can be identified to get the source.
//
//go:linkname Getsourcefile py.getsourcefile
func Getsourcefile(object *py.Object) *py.Object
// Return an absolute path to the source or compiled file for an object.
//
// The idea is for each object to have a unique origin, so this routine
// normalizes the result as much as possible.
//
//go:linkname Getabsfile py.getabsfile
func Getabsfile(object *py.Object, Filename *py.Object) *py.Object
// Return the module an object was defined in, or None if not found.
//
//go:linkname Getmodule py.getmodule
func Getmodule(object *py.Object, Filename *py.Object) *py.Object
// Return the entire source file and starting line number for an object.
//
// The argument may be a module, class, method, function, traceback, frame,
// or code object. The source code is returned as a list of all the lines
// in the file and the line number indexes a line in that list. An OSError
// is raised if the source code cannot be retrieved.
//
//go:linkname Findsource py.findsource
func Findsource(object *py.Object) *py.Object
// Get lines of comments immediately preceding an object's source code.
//
// Returns None when source can't be found.
//
//go:linkname Getcomments py.getcomments
func Getcomments(object *py.Object) *py.Object
// Extract the block of code at the top of the given list of lines.
//
//go:linkname Getblock py.getblock
func Getblock(lines *py.Object) *py.Object
// Return a list of source lines and starting line number for an object.
//
// The argument may be a module, class, method, function, traceback, frame,
// or code object. The source code is returned as a list of the lines
// corresponding to the object and the line number indicates where in the
// original source file the first line of code was found. An OSError is
// raised if the source code cannot be retrieved.
//
//go:linkname Getsourcelines py.getsourcelines
func Getsourcelines(object *py.Object) *py.Object
// Return the text of the source code for an object.
//
// The argument may be a module, class, method, function, traceback, frame,
// or code object. The source code is returned as a single string. An
// OSError is raised if the source code cannot be retrieved.
//
//go:linkname Getsource py.getsource
func Getsource(object *py.Object) *py.Object
// Recursive helper function for getclasstree().
//
//go:linkname Walktree py.walktree
func Walktree(classes *py.Object, children *py.Object, parent *py.Object) *py.Object
// Arrange the given list of classes into a hierarchy of nested lists.
//
// Where a nested list appears, it contains classes derived from the class
// whose entry immediately precedes the list. Each entry is a 2-tuple
// containing a class and a tuple of its base classes. If the 'unique'
// argument is true, exactly one entry appears in the returned structure
// for each class in the given list. Otherwise, classes using multiple
// inheritance and their descendants will appear multiple times.
//
//go:linkname Getclasstree py.getclasstree
func Getclasstree(classes *py.Object, unique *py.Object) *py.Object
// Get information about the arguments accepted by a code object.
//
// Three things are returned: (args, varargs, varkw), where
// 'args' is the list of argument names. Keyword-only arguments are
// appended. 'varargs' and 'varkw' are the names of the * and **
// arguments or None.
//
//go:linkname Getargs py.getargs
func Getargs(co *py.Object) *py.Object
// Get the names and default values of a callable object's parameters.
//
// A tuple of seven things is returned:
// (args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations).
// 'args' is a list of the parameter names.
// 'varargs' and 'varkw' are the names of the * and ** parameters or None.
// 'defaults' is an n-tuple of the default values of the last n parameters.
// 'kwonlyargs' is a list of keyword-only parameter names.
// 'kwonlydefaults' is a dictionary mapping names from kwonlyargs to defaults.
// 'annotations' is a dictionary mapping parameter names to annotations.
//
// Notable differences from inspect.signature():
// - the "self" parameter is always reported, even for bound methods
// - wrapper chains defined by __wrapped__ *not* unwrapped automatically
//
//go:linkname Getfullargspec py.getfullargspec
func Getfullargspec(func_ *py.Object) *py.Object
// Get information about arguments passed into a particular frame.
//
// A tuple of four things is returned: (args, varargs, varkw, locals).
// 'args' is a list of the argument names.
// 'varargs' and 'varkw' are the names of the * and ** arguments or None.
// 'locals' is the locals dictionary of the given frame.
//
//go:linkname Getargvalues py.getargvalues
func Getargvalues(frame *py.Object) *py.Object
// Get the mapping of arguments to values.
//
// A dict is returned, with keys the function argument names (including the
// names of the * and ** arguments, if any), and values the respective bound
// values from 'positional' and 'named'.
//
//go:linkname Getcallargs py.getcallargs
func Getcallargs(func_ *py.Object, __llgo_va_list ...interface{}) *py.Object
// Get the mapping of free variables to their current values.
//
// Returns a named tuple of dicts mapping the current nonlocal, global
// and builtin references as seen by the body of the function. A final
// set of unbound names that could not be resolved is also provided.
//
//go:linkname Getclosurevars py.getclosurevars
func Getclosurevars(func_ *py.Object) *py.Object
// Get information about a frame or traceback object.
//
// A tuple of five things is returned: the filename, the line number of
// the current line, the function name, a list of lines of context from
// the source code, and the index of the current line within that list.
// The optional second argument specifies the number of lines of context
// to return, which are centered around the current line.
//
//go:linkname Getframeinfo py.getframeinfo
func Getframeinfo(frame *py.Object, context *py.Object) *py.Object
// Get the line number from a frame object, allowing for optimization.
//
//go:linkname Getlineno py.getlineno
func Getlineno(frame *py.Object) *py.Object
// Get a list of records for a frame and all higher (calling) frames.
//
// Each record contains a frame object, filename, line number, function
// name, a list of lines of context, and index within the context.
//
//go:linkname Getouterframes py.getouterframes
func Getouterframes(frame *py.Object, context *py.Object) *py.Object
// Get a list of records for a traceback's frame and all lower frames.
//
// Each record contains a frame object, filename, line number, function
// name, a list of lines of context, and index within the context.
//
//go:linkname Getinnerframes py.getinnerframes
func Getinnerframes(tb *py.Object, context *py.Object) *py.Object
// Return the frame of the caller or None if this is not possible.
//
//go:linkname Currentframe py.currentframe
func Currentframe() *py.Object
// Return a list of records for the stack above the caller's frame.
//
//go:linkname Stack py.stack
func Stack(context *py.Object) *py.Object
// Return a list of records for the stack below the current exception.
//
//go:linkname Trace py.trace
func Trace(context *py.Object) *py.Object
// Get current state of a generator-iterator.
//
// Possible states are:
// GEN_CREATED: Waiting to start execution.
// GEN_RUNNING: Currently being executed by the interpreter.
// GEN_SUSPENDED: Currently suspended at a yield expression.
// GEN_CLOSED: Execution has completed.
//
//go:linkname Getgeneratorstate py.getgeneratorstate
func Getgeneratorstate(generator *py.Object) *py.Object
// Get the mapping of generator local variables to their current values.
//
// A dict is returned, with the keys the local variable names and values the
// bound values.
//
//go:linkname Getgeneratorlocals py.getgeneratorlocals
func Getgeneratorlocals(generator *py.Object) *py.Object
// Get current state of a coroutine object.
//
// Possible states are:
// CORO_CREATED: Waiting to start execution.
// CORO_RUNNING: Currently being executed by the interpreter.
// CORO_SUSPENDED: Currently suspended at an await expression.
// CORO_CLOSED: Execution has completed.
//
//go:linkname Getcoroutinestate py.getcoroutinestate
func Getcoroutinestate(coroutine *py.Object) *py.Object
// Get the mapping of coroutine local variables to their current values.
//
// A dict is returned, with the keys the local variable names and values the
// bound values.
//
//go:linkname Getcoroutinelocals py.getcoroutinelocals
func Getcoroutinelocals(coroutine *py.Object) *py.Object
// Get current state of an asynchronous generator object.
//
// Possible states are:
// AGEN_CREATED: Waiting to start execution.
// AGEN_RUNNING: Currently being executed by the interpreter.
// AGEN_SUSPENDED: Currently suspended at a yield expression.
// AGEN_CLOSED: Execution has completed.
//
//go:linkname Getasyncgenstate py.getasyncgenstate
func Getasyncgenstate(agen *py.Object) *py.Object
// Get the mapping of asynchronous generator local variables to their current
// values.
//
// A dict is returned, with the keys the local variable names and values the
// bound values.
//
//go:linkname Getasyncgenlocals py.getasyncgenlocals
func Getasyncgenlocals(agen *py.Object) *py.Object
// Get a signature object for the passed callable.
//
//go:linkname Signature py.signature
func Signature(obj *py.Object) *py.Object

BIN
py/inspect/llgo_autogen.lla Normal file

Binary file not shown.

152
py/json/gen.go Normal file
View File

@@ -0,0 +1,152 @@
package json
import (
_ "unsafe"
"github.com/goplus/llgo/py"
)
const LLGoPackage = "py.json"
// Serialize “obj“ as a JSON formatted stream to “fp“ (a
//
// ``.write()``-supporting file-like object).
//
// If ``skipkeys`` is true then ``dict`` keys that are not basic types
// (``str``, ``int``, ``float``, ``bool``, ``None``) will be skipped
// instead of raising a ``TypeError``.
//
// If ``ensure_ascii`` is false, then the strings written to ``fp`` can
// contain non-ASCII characters if they appear in strings contained in
// ``obj``. Otherwise, all such characters are escaped in JSON strings.
//
// If ``check_circular`` is false, then the circular reference check
// for container types will be skipped and a circular reference will
// result in an ``RecursionError`` (or worse).
//
// If ``allow_nan`` is false, then it will be a ``ValueError`` to
// serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``)
// in strict compliance of the JSON specification, instead of using the
// JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
//
// If ``indent`` is a non-negative integer, then JSON array elements and
// object members will be pretty-printed with that indent level. An indent
// level of 0 will only insert newlines. ``None`` is the most compact
// representation.
//
// If specified, ``separators`` should be an ``(item_separator, key_separator)``
// tuple. The default is ``(', ', ': ')`` if *indent* is ``None`` and
// ``(',', ': ')`` otherwise. To get the most compact JSON representation,
// you should specify ``(',', ':')`` to eliminate whitespace.
//
// ``default(obj)`` is a function that should return a serializable version
// of obj or raise TypeError. The default simply raises TypeError.
//
// If *sort_keys* is true (default: ``False``), then the output of
// dictionaries will be sorted by key.
//
// To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
// ``.default()`` method to serialize additional types), specify it with
// the ``cls`` kwarg; otherwise ``JSONEncoder`` is used.
//
//go:linkname Dump py.dump
func Dump(obj *py.Object, fp *py.Object) *py.Object
// Serialize “obj“ to a JSON formatted “str“.
//
// If ``skipkeys`` is true then ``dict`` keys that are not basic types
// (``str``, ``int``, ``float``, ``bool``, ``None``) will be skipped
// instead of raising a ``TypeError``.
//
// If ``ensure_ascii`` is false, then the return value can contain non-ASCII
// characters if they appear in strings contained in ``obj``. Otherwise, all
// such characters are escaped in JSON strings.
//
// If ``check_circular`` is false, then the circular reference check
// for container types will be skipped and a circular reference will
// result in an ``RecursionError`` (or worse).
//
// If ``allow_nan`` is false, then it will be a ``ValueError`` to
// serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in
// strict compliance of the JSON specification, instead of using the
// JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
//
// If ``indent`` is a non-negative integer, then JSON array elements and
// object members will be pretty-printed with that indent level. An indent
// level of 0 will only insert newlines. ``None`` is the most compact
// representation.
//
// If specified, ``separators`` should be an ``(item_separator, key_separator)``
// tuple. The default is ``(', ', ': ')`` if *indent* is ``None`` and
// ``(',', ': ')`` otherwise. To get the most compact JSON representation,
// you should specify ``(',', ':')`` to eliminate whitespace.
//
// ``default(obj)`` is a function that should return a serializable version
// of obj or raise TypeError. The default simply raises TypeError.
//
// If *sort_keys* is true (default: ``False``), then the output of
// dictionaries will be sorted by key.
//
// To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
// ``.default()`` method to serialize additional types), specify it with
// the ``cls`` kwarg; otherwise ``JSONEncoder`` is used.
//
//go:linkname Dumps py.dumps
func Dumps(obj *py.Object) *py.Object
// Deserialize “fp“ (a “.read()“-supporting file-like object containing
//
// a JSON document) to a Python object.
//
// ``object_hook`` is an optional function that will be called with the
// result of any object literal decode (a ``dict``). The return value of
// ``object_hook`` will be used instead of the ``dict``. This feature
// can be used to implement custom decoders (e.g. JSON-RPC class hinting).
//
// ``object_pairs_hook`` is an optional function that will be called with the
// result of any object literal decoded with an ordered list of pairs. The
// return value of ``object_pairs_hook`` will be used instead of the ``dict``.
// This feature can be used to implement custom decoders. If ``object_hook``
// is also defined, the ``object_pairs_hook`` takes priority.
//
// To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
// kwarg; otherwise ``JSONDecoder`` is used.
//
//go:linkname Load py.load
func Load(fp *py.Object) *py.Object
// Deserialize “s“ (a “str“, “bytes“ or “bytearray“ instance
//
// containing a JSON document) to a Python object.
//
// ``object_hook`` is an optional function that will be called with the
// result of any object literal decode (a ``dict``). The return value of
// ``object_hook`` will be used instead of the ``dict``. This feature
// can be used to implement custom decoders (e.g. JSON-RPC class hinting).
//
// ``object_pairs_hook`` is an optional function that will be called with the
// result of any object literal decoded with an ordered list of pairs. The
// return value of ``object_pairs_hook`` will be used instead of the ``dict``.
// This feature can be used to implement custom decoders. If ``object_hook``
// is also defined, the ``object_pairs_hook`` takes priority.
//
// ``parse_float``, if specified, will be called with the string
// of every JSON float to be decoded. By default this is equivalent to
// float(num_str). This can be used to use another datatype or parser
// for JSON floats (e.g. decimal.Decimal).
//
// ``parse_int``, if specified, will be called with the string
// of every JSON int to be decoded. By default this is equivalent to
// int(num_str). This can be used to use another datatype or parser
// for JSON integers (e.g. float).
//
// ``parse_constant``, if specified, will be called with one of the
// following strings: -Infinity, Infinity, NaN.
// This can be used to raise an exception if invalid JSON numbers
// are encountered.
//
// To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
// kwarg; otherwise ``JSONDecoder`` is used.
//
//go:linkname Loads py.loads
func Loads(s *py.Object) *py.Object

BIN
py/json/llgo_autogen.lla Normal file

Binary file not shown.

96
py/list.go Normal file
View File

@@ -0,0 +1,96 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package py
import (
_ "unsafe"
"github.com/goplus/llgo/c"
)
// https://docs.python.org/3/c-api/list.html
//go:linkname List llgo.pyList
func List(__llgo_va_list ...any) *Object
// Return a new list of length len on success, or nil on failure.
//
//go:linkname NewList C.PyList_New
func NewList(len uintptr) *Object
// Return the length of the list object in list; this is equivalent to len(list)
// on a list object.
//
// llgo:link (*Object).ListLen C.PyList_Size
func (l *Object) ListLen() uintptr { return 0 }
// Return the object at position index in the list pointed to by list. The position
// must be non-negative; indexing from the end of the list is not supported. If index
// is out of bounds (<0 or >=len(list)), return nil and set an IndexError exception.
//
// llgo:link (*Object).ListItem C.PyList_GetItem
func (l *Object) ListItem(index uintptr) *Object { return nil }
// Set the item at index index in list to item. Return 0 on success. If index is out
// of bounds, return -1 and set an IndexError exception.
//
// llgo:link (*Object).ListSetItem C.PyList_SetItem
func (l *Object) ListSetItem(index uintptr, item *Object) c.Int { return 0 }
// Insert the item item into list list in front of index index. Return 0 if successful;
// return -1 and set an exception if unsuccessful. Analogous to list.insert(index, item).
//
// llgo:link (*Object).ListInsert C.PyList_Insert
func (l *Object) ListInsert(index uintptr, item *Object) c.Int { return 0 }
// Append the object item at the end of list list. Return 0 if successful; return -1
// and set an exception if unsuccessful. Analogous to list.append(item).
//
// llgo:link (*Object).ListAppend C.PyList_Append
func (l *Object) ListAppend(item *Object) c.Int { return 0 }
// Return a list of the objects in list containing the objects between low and high.
// Return nil and set an exception if unsuccessful. Analogous to list[low:high].
// Indexing from the end of the list is not supported.
//
// llgo:link (*Object).ListSlice C.PyList_GetSlice
func (l *Object) ListSlice(low, high uintptr) *Object { return nil }
// Set the slice of list between low and high to the contents of itemlist. Analogous
// to list[low:high] = itemlist. The itemlist may be NULL, indicating the assignment
// of an empty list (slice deletion). Return 0 on success, -1 on failure. Indexing
// from the end of the list is not supported.
//
// llgo:link (*Object).ListSetSlice C.PyList_SetSlice
func (l *Object) ListSetSlice(low, high uintptr, itemlist *Object) c.Int { return 0 }
// Sort the items of list in place. Return 0 on success, -1 on failure. This is equivalent
// to list.sort().
//
// llgo:link (*Object).ListSort C.PyList_Sort
func (l *Object) ListSort() c.Int { return 0 }
// Reverse the items of list in place. Return 0 on success, -1 on failure. This is the
// equivalent of list.reverse().
//
// llgo:link (*Object).ListReverse C.PyList_Reverse
func (l *Object) ListReverse() c.Int { return 0 }
// Return a new tuple object containing the contents of list; equivalent to tuple(list).
//
// llgo:link (*Object).ListAsTuple C.PyList_AsTuple
func (l *Object) ListAsTuple() *Object { return nil }

7
py/llgo.cfg Normal file
View File

@@ -0,0 +1,7 @@
{
"cl": [
"clang -emit-llvm -S -o module.ll -c _pyg/module.c",
"llgen .",
"rm llgo_autogen.lla; zip llgo_autogen.lla llgo_autogen.ll module.ll",
]
}

BIN
py/llgo_autogen.lla Normal file

Binary file not shown.

73
py/long.go Normal file
View File

@@ -0,0 +1,73 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package py
import (
_ "unsafe"
"github.com/goplus/llgo/c"
)
// https://docs.python.org/3/c-api/long.html
//go:linkname Long C.PyLong_FromLong
func Long(v c.Long) *Object
//go:linkname LongLong C.PyLong_FromLongLong
func LongLong(v c.LongLong) *Object
//go:linkname Ulong C.PyLong_FromUnsignedLong
func Ulong(v c.Ulong) *Object
//go:linkname UlongLong C.PyLong_FromUnsignedLongLong
func UlongLong(v c.UlongLong) *Object
//go:linkname Uintptr C.PyLong_FromSize_t
func Uintptr(v uintptr) *Object
//go:linkname LongFromFloat64 C.PyLong_FromDouble
func LongFromFloat64(v float64) *Object
//go:linkname LongFromVoidPtr C.PyLong_FromVoidPtr
func LongFromVoidPtr(v c.Pointer) *Object
//go:linkname LongFromCStr C.PyLong_FromString
func LongFromCStr(v *c.Char, pend **c.Char, base c.Int) *Object
//go:linkname LongFromUnicode C.PyLong_FromUnicodeObject
func LongFromUnicode(v *Object, base c.Int) *Object
// llgo:link (*Object).Long C.PyLong_AsLong
func (l *Object) Long() c.Long { return 0 }
// llgo:link (*Object).LongLong C.PyLong_AsLongLong
func (l *Object) LongLong() c.LongLong { return 0 }
// llgo:link (*Object).Ulong C.PyLong_AsUnsignedLong
func (l *Object) Ulong() c.Ulong { return 0 }
// llgo:link (*Object).UlongLong C.PyLong_AsUnsignedLongLong
func (l *Object) UlongLong() c.UlongLong { return 0 }
// llgo:link (*Object).Uintptr C.PyLong_AsSize_t
func (l *Object) Uintptr() uintptr { return 0 }
// llgo:link (*Object).LongAsFloat64 C.PyLong_AsDouble
func (l *Object) LongAsFloat64() float64 { return 0 }
// llgo:link (*Object).LongAsVoidPtr C.PyLong_AsVoidPtr
func (l *Object) LongAsVoidPtr() c.Pointer { return nil }

31
py/math/doc.txt Normal file
View File

@@ -0,0 +1,31 @@
// Unlike the built-in ** operator, math.pow() converts both its arguments to type
// float. Use ** or the built-in pow() function for computing exact integer powers.
//
//go:linkname Pow py.pow
func Pow(x, y *py.Object) *py.Object
// Return the sine of x radians.
//
//go:linkname Sin py.sin
func Sin(x *py.Object) *py.Object
// Return the hyperbolic sine of x.
//
//go:linkname Sinh py.sinh
func Sinh(x *py.Object) *py.Object
// Return the base-2 logarithm of x. This is usually more accurate than log(x, 2).
//
//go:linkname Log2 py.log2
func Log2(x *py.Object) *py.Object
// Return the base-10 logarithm of x. This is usually more accurate than log(x, 10).
//
//go:linkname Log10 py.log10
func Log10(x *py.Object) *py.Object
// Return the fractional and integer parts of x. Both results carry the sign of
// x and are floats.
//
//go:linkname Modf py.modf
func Modf(x *py.Object) *py.Object

349
py/math/gen.go Normal file
View File

@@ -0,0 +1,349 @@
package math
import (
_ "unsafe"
"github.com/goplus/llgo/py"
)
const LLGoPackage = "py.math"
// Return the arc cosine (measured in radians) of x.
//
// The result is between 0 and pi.
//
//go:linkname Acos py.acos
func Acos(x *py.Object) *py.Object
// Return the inverse hyperbolic cosine of x.
//
//go:linkname Acosh py.acosh
func Acosh(x *py.Object) *py.Object
// Return the arc sine (measured in radians) of x.
//
// The result is between -pi/2 and pi/2.
//
//go:linkname Asin py.asin
func Asin(x *py.Object) *py.Object
// Return the inverse hyperbolic sine of x.
//
//go:linkname Asinh py.asinh
func Asinh(x *py.Object) *py.Object
// Return the arc tangent (measured in radians) of x.
//
// The result is between -pi/2 and pi/2.
//
//go:linkname Atan py.atan
func Atan(x *py.Object) *py.Object
// Return the arc tangent (measured in radians) of y/x.
//
// Unlike atan(y/x), the signs of both x and y are considered.
//
//go:linkname Atan2 py.atan2
func Atan2(y *py.Object, x *py.Object) *py.Object
// Return the inverse hyperbolic tangent of x.
//
//go:linkname Atanh py.atanh
func Atanh(x *py.Object) *py.Object
// Return the cube root of x.
//
//go:linkname Cbrt py.cbrt
func Cbrt(x *py.Object) *py.Object
// Return the ceiling of x as an Integral.
//
// This is the smallest integer >= x.
//
//go:linkname Ceil py.ceil
func Ceil(x *py.Object) *py.Object
// Return a float with the magnitude (absolute value) of x but the sign of y.
//
// On platforms that support signed zeros, copysign(1.0, -0.0)
// returns -1.0.
//
//go:linkname Copysign py.copysign
func Copysign(x *py.Object, y *py.Object) *py.Object
// Return the cosine of x (measured in radians).
//
//go:linkname Cos py.cos
func Cos(x *py.Object) *py.Object
// Return the hyperbolic cosine of x.
//
//go:linkname Cosh py.cosh
func Cosh(x *py.Object) *py.Object
// Convert angle x from radians to degrees.
//
//go:linkname Degrees py.degrees
func Degrees(x *py.Object) *py.Object
// Return the Euclidean distance between two points p and q.
//
// The points should be specified as sequences (or iterables) of
// coordinates. Both inputs must have the same dimension.
//
// Roughly equivalent to:
//
// sqrt(sum((px - qx) ** 2.0 for px, qx in zip(p, q)))
//
//go:linkname Dist py.dist
func Dist(p *py.Object, q *py.Object) *py.Object
// Error function at x.
//
//go:linkname Erf py.erf
func Erf(x *py.Object) *py.Object
// Complementary error function at x.
//
//go:linkname Erfc py.erfc
func Erfc(x *py.Object) *py.Object
// Return e raised to the power of x.
//
//go:linkname Exp py.exp
func Exp(x *py.Object) *py.Object
// Return 2 raised to the power of x.
//
//go:linkname Exp2 py.exp2
func Exp2(x *py.Object) *py.Object
// Return exp(x)-1.
//
// This function avoids the loss of precision involved in the direct evaluation of exp(x)-1 for small x.
//
//go:linkname Expm1 py.expm1
func Expm1(x *py.Object) *py.Object
// Return the absolute value of the float x.
//
//go:linkname Fabs py.fabs
func Fabs(x *py.Object) *py.Object
// Find n!.
//
// Raise a ValueError if x is negative or non-integral.
//
//go:linkname Factorial py.factorial
func Factorial(n *py.Object) *py.Object
// Return the floor of x as an Integral.
//
// This is the largest integer <= x.
//
//go:linkname Floor py.floor
func Floor(x *py.Object) *py.Object
// Return fmod(x, y), according to platform C.
//
// x % y may differ.
//
//go:linkname Fmod py.fmod
func Fmod(x *py.Object, y *py.Object) *py.Object
// Return the mantissa and exponent of x, as pair (m, e).
//
// m is a float and e is an int, such that x = m * 2.**e.
// If x is 0, m and e are both 0. Else 0.5 <= abs(m) < 1.0.
//
//go:linkname Frexp py.frexp
func Frexp(x *py.Object) *py.Object
// Return an accurate floating point sum of values in the iterable seq.
//
// Assumes IEEE-754 floating point arithmetic.
//
//go:linkname Fsum py.fsum
func Fsum(seq *py.Object) *py.Object
// Gamma function at x.
//
//go:linkname Gamma py.gamma
func Gamma(x *py.Object) *py.Object
// Greatest Common Divisor.
//
//go:linkname Gcd py.gcd
func Gcd(__llgo_va_list ...interface{}) *py.Object
// Return True if x is neither an infinity nor a NaN, and False otherwise.
//
//go:linkname Isfinite py.isfinite
func Isfinite(x *py.Object) *py.Object
// Return True if x is a positive or negative infinity, and False otherwise.
//
//go:linkname Isinf py.isinf
func Isinf(x *py.Object) *py.Object
// Return True if x is a NaN (not a number), and False otherwise.
//
//go:linkname Isnan py.isnan
func Isnan(x *py.Object) *py.Object
// Return the integer part of the square root of the input.
//
//go:linkname Isqrt py.isqrt
func Isqrt(n *py.Object) *py.Object
// Least Common Multiple.
//
//go:linkname Lcm py.lcm
func Lcm(__llgo_va_list ...interface{}) *py.Object
// Return x * (2**i).
//
// This is essentially the inverse of frexp().
//
//go:linkname Ldexp py.ldexp
func Ldexp(x *py.Object, i *py.Object) *py.Object
// Natural logarithm of absolute value of Gamma function at x.
//
//go:linkname Lgamma py.lgamma
func Lgamma(x *py.Object) *py.Object
// Return the base 10 logarithm of x.
//
//go:linkname Log10 py.log10
func Log10(x *py.Object) *py.Object
// Return the base 2 logarithm of x.
//
//go:linkname Log2 py.log2
func Log2(x *py.Object) *py.Object
// Return the fractional and integer parts of x.
//
// Both results carry the sign of x and are floats.
//
//go:linkname Modf py.modf
func Modf(x *py.Object) *py.Object
// Return x**y (x to the power of y).
//
//go:linkname Pow py.pow
func Pow(x *py.Object, y *py.Object) *py.Object
// Convert angle x from degrees to radians.
//
//go:linkname Radians py.radians
func Radians(x *py.Object) *py.Object
// Difference between x and the closest integer multiple of y.
//
// Return x - n*y where n*y is the closest integer multiple of y.
// In the case where x is exactly halfway between two multiples of
// y, the nearest even value of n is used. The result is always exact.
//
//go:linkname Remainder py.remainder
func Remainder(x *py.Object, y *py.Object) *py.Object
// Return the sine of x (measured in radians).
//
//go:linkname Sin py.sin
func Sin(x *py.Object) *py.Object
// Return the hyperbolic sine of x.
//
//go:linkname Sinh py.sinh
func Sinh(x *py.Object) *py.Object
// Return the square root of x.
//
//go:linkname Sqrt py.sqrt
func Sqrt(x *py.Object) *py.Object
// Return the tangent of x (measured in radians).
//
//go:linkname Tan py.tan
func Tan(x *py.Object) *py.Object
// Return the hyperbolic tangent of x.
//
//go:linkname Tanh py.tanh
func Tanh(x *py.Object) *py.Object
// Return the sum of products of values from two iterables p and q.
//
// Roughly equivalent to:
//
// sum(itertools.starmap(operator.mul, zip(p, q, strict=True)))
//
// For float and mixed int/float inputs, the intermediate products
// and sums are computed with extended precision.
//
//go:linkname Sumprod py.sumprod
func Sumprod(p *py.Object, q *py.Object) *py.Object
// Truncates the Real x to the nearest Integral toward 0.
//
// Uses the __trunc__ magic method.
//
//go:linkname Trunc py.trunc
func Trunc(x *py.Object) *py.Object
// Calculate the product of all the elements in the input iterable.
//
// The default start value for the product is 1.
//
// When the iterable is empty, return the start value. This function is
// intended specifically for use with numeric values and may reject
// non-numeric types.
//
//go:linkname Prod py.prod
func Prod(iterable *py.Object) *py.Object
// Number of ways to choose k items from n items without repetition and with order.
//
// Evaluates to n! / (n - k)! when k <= n and evaluates
// to zero when k > n.
//
// If k is not specified or is None, then k defaults to n
// and the function returns n!.
//
// Raises TypeError if either of the arguments are not integers.
// Raises ValueError if either of the arguments are negative.
//
//go:linkname Perm py.perm
func Perm(n *py.Object, k *py.Object) *py.Object
// Number of ways to choose k items from n items without repetition and without order.
//
// Evaluates to n! / (k! * (n - k)!) when k <= n and evaluates
// to zero when k > n.
//
// Also called the binomial coefficient because it is equivalent
// to the coefficient of k-th term in polynomial expansion of the
// expression (1 + x)**n.
//
// Raises TypeError if either of the arguments are not integers.
// Raises ValueError if either of the arguments are negative.
//
//go:linkname Comb py.comb
func Comb(n *py.Object, k *py.Object) *py.Object
// Return the floating-point value the given number of steps after x towards y.
//
// If steps is not specified or is None, it defaults to 1.
//
// Raises a TypeError, if x or y is not a double, or if steps is not an integer.
// Raises ValueError if steps is negative.
//
//go:linkname Nextafter py.nextafter
func Nextafter(x *py.Object, y *py.Object) *py.Object
// Return the value of the least significant bit of the float x.
//
//go:linkname Ulp py.ulp
func Ulp(x *py.Object) *py.Object

BIN
py/math/llgo_autogen.lla Normal file

Binary file not shown.

51
py/math/math.go Normal file
View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package math
import (
_ "unsafe"
"github.com/goplus/llgo/py"
)
// https://docs.python.org/3/library/math.html
//go:linkname Pi py.pi
var Pi *py.Object
// With one argument, return the natural logarithm of x (to base e).
//
//go:linkname Log py.log
func Log(x *py.Object) *py.Object
// With two arguments, return the logarithm of x to the given base, calculated
// as log(x)/log(base).
//
//go:linkname LogOf py.log
func LogOf(x, base *py.Object) *py.Object
// Return the natural logarithm of 1+x (base e). The result is calculated in
// a way which is accurate for x near zero.
//
//go:linkname Log1p py.log1p
func Log1p(x *py.Object) *py.Object
// Return the Euclidean norm, sqrt(sum(x**2 for x in coordinates)). This is the
// length of the vector from the origin to the point given by the coordinates.
//
//go:linkname Hypot py.hypot
func Hypot(coordinates ...*py.Object) *py.Object

78
py/module.go Normal file
View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package py
import (
_ "unsafe"
"github.com/goplus/llgo/c"
)
// https://docs.python.org/3/c-api/import.html
// https://docs.python.org/3/c-api/module.html
/*
// llgo:type C
type ModuleDefBase struct {
Unused [8]byte // TODO(xsw)
}
// llgo:type C
type ModuleDef struct {
Base ModuleDefBase
// TODO(xsw)
}
*/
// Return the module object corresponding to a module name. The name argument
// may be of the form package.module. First check the modules dictionary if
// theres one there, and if not, create a new one and insert it in the modules
// dictionary. Return nil with an exception set on failure.
//
//go:linkname AddModule C.PyImport_AddModule
func AddModule(name *c.Char) *Object
// This is a wrapper around py.Import which takes a const char* as an argument
// instead of an Object.
//
//go:linkname ImportModule C.PyImport_ImportModule
func ImportModule(name *c.Char) *Object
// This is a higher-level interface that calls the current “import hook function” (with
// an explicit level of 0, meaning absolute import). It invokes the __import__() function
// from the __builtins__ of the current globals. This means that the import is done using
// whatever import hooks are installed in the current environment.
//
// This function always uses absolute imports.
//
//go:linkname Import C.PyImport_Import
func Import(name *Object) *Object
// Return the dictionary object that implements modules namespace; this object is the same
// as the __dict__ attribute of the module object. If module is not a module object (or a
// subtype of a module object), SystemError is raised and nil is returned.
//
// It is recommended extensions use other Module and Object functions rather than directly
// manipulate a modules __dict__.
//
// llgo:link (*Object).ModuleGetDict C.PyModule_GetDict
func (m *Object) ModuleGetDict() *Object { return nil }
// llgo:link (*Object).ModuleLoadSyms C.llgoLoadPyModSyms
func (m *Object) ModuleLoadSyms(__llgo_va_list ...any) {}
// -----------------------------------------------------------------------------

82
py/module.ll Normal file
View File

@@ -0,0 +1,82 @@
; ModuleID = '_pyg/module.c'
source_filename = "_pyg/module.c"
%struct.PyObject = type opaque
; Function Attrs: noinline nounwind optnone ssp uwtable(sync)
define void @llgoLoadPyModSyms(%struct.PyObject* noundef %0, ...) #0 {
%2 = alloca %struct.PyObject*, align 8
%3 = alloca i8*, align 8
%4 = alloca i8*, align 8
%5 = alloca i8*, align 8
%6 = alloca %struct.PyObject**, align 8
%7 = alloca %struct.PyObject**, align 8
store %struct.PyObject* %0, %struct.PyObject** %2, align 8
%8 = bitcast i8** %3 to i8*
call void @llvm.va_start(i8* %8)
br label %9
9: ; preds = %26, %1
%10 = va_arg i8** %3, i8*
store i8* %10, i8** %5, align 8
%11 = load i8*, i8** %5, align 8
store i8* %11, i8** %4, align 8
%12 = load i8*, i8** %4, align 8
%13 = icmp eq i8* %12, null
br i1 %13, label %14, label %15
14: ; preds = %9
br label %27
15: ; preds = %9
%16 = va_arg i8** %3, %struct.PyObject**
store %struct.PyObject** %16, %struct.PyObject*** %7, align 8
%17 = load %struct.PyObject**, %struct.PyObject*** %7, align 8
store %struct.PyObject** %17, %struct.PyObject*** %6, align 8
%18 = load %struct.PyObject**, %struct.PyObject*** %6, align 8
%19 = load %struct.PyObject*, %struct.PyObject** %18, align 8
%20 = icmp eq %struct.PyObject* %19, null
br i1 %20, label %21, label %26
21: ; preds = %15
%22 = load %struct.PyObject*, %struct.PyObject** %2, align 8
%23 = load i8*, i8** %4, align 8
%24 = call %struct.PyObject* @PyObject_GetAttrString(%struct.PyObject* noundef %22, i8* noundef %23)
%25 = load %struct.PyObject**, %struct.PyObject*** %6, align 8
store %struct.PyObject* %24, %struct.PyObject** %25, align 8
br label %26
26: ; preds = %21, %15
br label %9
27: ; preds = %14
%28 = bitcast i8** %3 to i8*
call void @llvm.va_end(i8* %28)
ret void
}
; Function Attrs: nocallback nofree nosync nounwind willreturn
declare void @llvm.va_start(i8*) #1
declare %struct.PyObject* @PyObject_GetAttrString(%struct.PyObject* noundef, i8* noundef) #2
; Function Attrs: nocallback nofree nosync nounwind willreturn
declare void @llvm.va_end(i8*) #1
attributes #0 = { noinline nounwind optnone ssp uwtable(sync) "frame-pointer"="non-leaf" "min-legal-vector-width"="0" "no-trapping-math"="true" "probe-stack"="__chkstk_darwin" "stack-protector-buffer-size"="8" "target-cpu"="apple-m1" "target-features"="+aes,+crc,+crypto,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+v8.5a,+zcm,+zcz" }
attributes #1 = { nocallback nofree nosync nounwind willreturn }
attributes #2 = { "frame-pointer"="non-leaf" "no-trapping-math"="true" "probe-stack"="__chkstk_darwin" "stack-protector-buffer-size"="8" "target-cpu"="apple-m1" "target-features"="+aes,+crc,+crypto,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+v8.5a,+zcm,+zcz" }
!llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6, !7, !8}
!llvm.ident = !{!9}
!0 = !{i32 2, !"SDK Version", [2 x i32] [i32 13, i32 3]}
!1 = !{i32 1, !"wchar_size", i32 4}
!2 = !{i32 8, !"branch-target-enforcement", i32 0}
!3 = !{i32 8, !"sign-return-address", i32 0}
!4 = !{i32 8, !"sign-return-address-all", i32 0}
!5 = !{i32 8, !"sign-return-address-with-bkey", i32 0}
!6 = !{i32 7, !"PIC Level", i32 2}
!7 = !{i32 7, !"uwtable", i32 1}
!8 = !{i32 7, !"frame-pointer", i32 1}
!9 = !{!"Apple clang version 14.0.3 (clang-1403.0.22.14.1)"}

10195
py/numpy/gen.go Normal file

File diff suppressed because it is too large Load Diff

BIN
py/numpy/llgo_autogen.lla Normal file

Binary file not shown.

79
py/numpy/numpy.go Normal file
View File

@@ -0,0 +1,79 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package numpy
import (
_ "unsafe"
"github.com/goplus/llgo/py"
)
// https://numpy.org/doc/stable/reference/index.html#reference
// Return evenly spaced values within a given interval.
//
// numpy.arange([start, ]stop, [step, ]dtype=None, *, like=None)
//
// See https://numpy.org/doc/stable/reference/generated/numpy.arange.html#numpy-arange
//
//go:linkname Arange py.arange
func Arange(start, stop, step, dtype *py.Object) *py.Object
// Return a new array of given shape and type, without initializing entries.
//
// numpy.empty(shape, dtype=float, order='C', *, like=None)
//
// See https://numpy.org/doc/stable/reference/generated/numpy.empty.html#numpy-empty
//
//go:linkname Empty py.empty
func Empty(shape, dtype, order *py.Object) *py.Object
// Return a 2-D array with ones on the diagonal and zeros elsewhere.
//
// numpy.eye(N, M=None, k=0, dtype=<class 'float'>, order='C', *, like=None)
//
// See https://numpy.org/doc/stable/reference/generated/numpy.eye.html#numpy-eye
//
//go:linkname Eye py.eye
func Eye(N, M, k, dtype, order *py.Object) *py.Object
// Return a new array of given shape and type, filled with zeros.
//
// numpy.zeros(shape, dtype=float, order='C', *, like=None)
//
// See https://numpy.org/doc/stable/reference/generated/numpy.zeros.html#numpy-zeros
//
//go:linkname Zeros py.zeros
func Zeros(shape, dtype, order *py.Object) *py.Object
// Create an array.
//
// numpy.array(object, dtype=None, *, copy=True, order='K', subok=False, ndmin=0, like=None)
//
// See https://numpy.org/doc/stable/reference/generated/numpy.array.html#numpy-array
//
//go:linkname Array py.array
func Array(object, dtype *py.Object) *py.Object
// Convert the input to an array.
//
// numpy.asarray(a, dtype=None, order=None, *, like=None)
//
// See https://numpy.org/doc/stable/reference/generated/numpy.asarray.html#numpy-asarray
//
//go:linkname AsArray py.asarray
func AsArray(a, dtype, order *py.Object) *py.Object

68
py/object.go Normal file
View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package py
import (
_ "unsafe"
"github.com/goplus/llgo/c"
)
// https://docs.python.org/3/c-api/object.html
// Object represents a Python object.
type Object struct {
Unused [8]byte
}
// llgo:link (*Object).DecRef C.Py_DecRef
func (o *Object) DecRef() {}
// llgo:link (*Object).Type C.PyObject_Type
func (o *Object) Type() *Object { return nil }
// Compute a string representation of object o. Returns the string representation on
// success, nil on failure. This is the equivalent of the Python expression str(o).
// Called by the str() built-in function and, therefore, by the print() function.
//
// llgo:link (*Object).Str C.PyObject_Str
func (o *Object) Str() *Object { return nil }
// Returns 1 if the object o is considered to be true, and 0 otherwise. This is equivalent
// to the Python expression not not o. On failure, return -1.
//
// llgo:link (*Object).IsTrue C.PyObject_IsTrue
func (o *Object) IsTrue() c.Int { return -1 }
// Returns 0 if the object o is considered to be true, and 1 otherwise. This is equivalent
// to the Python expression not o. On failure, return -1.
//
// llgo:link (*Object).NotTrue C.PyObject_Not
func (o *Object) NotTrue() c.Int { return -1 }
// -----------------------------------------------------------------------------
// Retrieve an attribute named attrName from object o. Returns the attribute value on success,
// or nil on failure. This is the equivalent of the Python expression o.attrName.
//
// llgo:link (*Object).GetAttr C.PyObject_GetAttr
func (o *Object) GetAttr(attrName *Object) *Object { return nil }
// llgo:link (*Object).GetAttrString C.PyObject_GetAttrString
func (o *Object) GetAttrString(attrName *c.Char) *Object { return nil }
// -----------------------------------------------------------------------------

1429
py/os/gen.go Normal file

File diff suppressed because it is too large Load Diff

BIN
py/os/llgo_autogen.lla Normal file

Binary file not shown.

42
py/os/os.go Normal file
View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package os
import (
_ "unsafe"
"github.com/goplus/llgo/py"
)
// https://docs.python.org/3/library/os.html
// Rename the file or directory src to dst. If dst exists, the operation will
// fail with an OSError subclass in a number of cases:
//
// On Windows, if dst exists a FileExistsError is always raised. The operation
// may fail if src and dst are on different filesystems. Use shutil.move() to
// support moves to a different filesystem.
//
// On Unix, if src is a file and dst is a directory or vice-versa, an IsADirectoryError
// or a NotADirectoryError will be raised respectively. If both are directories and dst
// is empty, dst will be silently replaced. If dst is a non-empty directory, an OSError
// is raised. If both are files, dst will be replaced silently if the user has permission.
// The operation may fail on some Unix flavors if src and dst are on different filesystems.
// If successful, the renaming will be an atomic operation (this is a POSIX requirement).
//
//go:linkname Rename py.rename
func Rename(src, dst *py.Object) *py.Object

120
py/python.go Normal file
View File

@@ -0,0 +1,120 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package py
import (
_ "unsafe"
"github.com/goplus/llgo/c"
)
const (
LLGoPackage = "link: $LLGO_LIB_PYTHON"
)
// -----------------------------------------------------------------------------
//go:linkname SetProgramName C.Py_SetProgramName
func SetProgramName(name *c.Char)
//go:linkname Initialize C.Py_Initialize
func Initialize()
// This function works like Initialize() if initsigs is 1.
// If initsigs is 0, it skips initialization registration of signal handlers,
// which might be useful when Python is embedded.
//
//go:linkname InitializeEx C.Py_InitializeEx
func InitializeEx(initsigs c.Int)
//go:linkname Finalize C.Py_Finalize
func Finalize()
// -----------------------------------------------------------------------------
//go:linkname RunSimpleString C.PyRun_SimpleString
func RunSimpleString(command *c.Char) c.Int
//go:linkname RunSimpleStringFlags C.PyRun_SimpleStringFlags
func RunSimpleStringFlags(command *c.Char, flags *CompilerFlags) c.Int
//go:linkname RunSimpleFile C.PyRun_SimpleFile
func RunSimpleFile(fp c.FilePtr, filename *c.Char) c.Int
//go:linkname RunSimpleFileFlags C.PyRun_SimpleFileFlags
func RunSimpleFileFlags(fp c.FilePtr, filename *c.Char, flags *CompilerFlags) c.Int
// -----------------------------------------------------------------------------
type InputType c.Int
const (
SingleInput InputType = 256 // read code from i/o
FileInput InputType = 257 // read code from filename
EvalInput InputType = 258 // read code from string
// FuncTypeInput InputType = 345
)
// llgo:type C
type CompilerFlags struct {
CfFlags c.Int
}
//go:linkname CompileString C.Py_CompileString
func CompileString(str, filename *c.Char, start InputType) *Object
//go:linkname CompileStringFlags C.Py_CompileStringFlags
func CompileStringFlags(str, filename *c.Char, start InputType, flags *CompilerFlags) *Object
//go:linkname CompileStringExFlags C.Py_CompileStringExFlags
func CompileStringExFlags(str, filename *c.Char, start InputType, flags *CompilerFlags, optimize c.Int) *Object
// Parse and compile the Python source code in str, returning the resulting code object.
// The start token is given by start; this can be used to constrain the code which can be
// compiled and should be py.EvalInput, py.FileInput, or py.SingleInput. The filename
// specified by filename is used to construct the code object and may appear in tracebacks
// or SyntaxError exception messages. This returns NULL if the code cannot be parsed or
// compiled.
//
// The integer optimize specifies the optimization level of the compiler; a value of -1
// selects the optimization level of the interpreter as given by -O options. Explicit levels
// are 0 (no optimization; __debug__ is true), 1 (asserts are removed, __debug__ is false) or
// 2 (docstrings are removed too).
//
//go:linkname CompileStringObject C.Py_CompileStringObject
func CompileStringObject(str *c.Char, filename *Object, start InputType, flags *CompilerFlags, optimize c.Int) *Object
// -----------------------------------------------------------------------------
// This is a simplified interface to EvalCodeEx, with just the code object, and global and
// local variables. The other arguments are set to nil.
//
//go:linkname EvalCode C.PyEval_EvalCode
func EvalCode(code, globals, locals *Object) *Object
// Evaluate a precompiled code object, given a particular environment for its evaluation.
// This environment consists of a dictionary of global variables, a mapping object of local
// variables, arrays of arguments, keywords and defaults, a dictionary of default values for
// keyword-only arguments and a closure tuple of cells.
//
//go:linkname EvalCodeEx C.PyEval_EvalCodeEx
func EvalCodeEx(
code, globals, locals *Object,
args *Object, argcount c.Int, kws *Object, kwcount c.Int,
defs *Object, defcount c.Int, kwdefs, closure *Object) *Object
// -----------------------------------------------------------------------------

401
py/statistics/gen.go Normal file
View File

@@ -0,0 +1,401 @@
package statistics
import (
_ "unsafe"
"github.com/goplus/llgo/py"
)
const LLGoPackage = "py.statistics"
// Error function at x.
//
//go:linkname Erf py.erf
func Erf(x *py.Object) *py.Object
// Return the sample arithmetic mean of data.
//
// >>> mean([1, 2, 3, 4, 4])
// 2.8
//
// >>> from fractions import Fraction as F
// >>> mean([F(3, 7), F(1, 21), F(5, 3), F(1, 3)])
// Fraction(13, 21)
//
// >>> from decimal import Decimal as D
// >>> mean([D("0.5"), D("0.75"), D("0.625"), D("0.375")])
// Decimal('0.5625')
//
// If ``data`` is empty, StatisticsError will be raised.
//
//go:linkname Mean py.mean
func Mean(data *py.Object) *py.Object
// Convert data to floats and compute the arithmetic mean.
//
// This runs faster than the mean() function and it always returns a float.
// If the input dataset is empty, it raises a StatisticsError.
//
// >>> fmean([3.5, 4.0, 5.25])
// 4.25
//
//go:linkname Fmean py.fmean
func Fmean(data *py.Object, weights *py.Object) *py.Object
// Convert data to floats and compute the geometric mean.
//
// Raises a StatisticsError if the input dataset is empty,
// if it contains a zero, or if it contains a negative value.
//
// No special efforts are made to achieve exact results.
// (However, this may change in the future.)
//
// >>> round(geometric_mean([54, 24, 36]), 9)
// 36.0
//
//go:linkname GeometricMean py.geometric_mean
func GeometricMean(data *py.Object) *py.Object
// Return the harmonic mean of data.
//
// The harmonic mean is the reciprocal of the arithmetic mean of the
// reciprocals of the data. It can be used for averaging ratios or
// rates, for example speeds.
//
// Suppose a car travels 40 km/hr for 5 km and then speeds-up to
// 60 km/hr for another 5 km. What is the average speed?
//
// >>> harmonic_mean([40, 60])
// 48.0
//
// Suppose a car travels 40 km/hr for 5 km, and when traffic clears,
// speeds-up to 60 km/hr for the remaining 30 km of the journey. What
// is the average speed?
//
// >>> harmonic_mean([40, 60], weights=[5, 30])
// 56.0
//
// If ``data`` is empty, or any element is less than zero,
// ``harmonic_mean`` will raise ``StatisticsError``.
//
//go:linkname HarmonicMean py.harmonic_mean
func HarmonicMean(data *py.Object, weights *py.Object) *py.Object
// Return the median (middle value) of numeric data.
//
// When the number of data points is odd, return the middle data point.
// When the number of data points is even, the median is interpolated by
// taking the average of the two middle values:
//
// >>> median([1, 3, 5])
// 3
// >>> median([1, 3, 5, 7])
// 4.0
//
//go:linkname Median py.median
func Median(data *py.Object) *py.Object
// Return the low median of numeric data.
//
// When the number of data points is odd, the middle value is returned.
// When it is even, the smaller of the two middle values is returned.
//
// >>> median_low([1, 3, 5])
// 3
// >>> median_low([1, 3, 5, 7])
// 3
//
//go:linkname MedianLow py.median_low
func MedianLow(data *py.Object) *py.Object
// Return the high median of data.
//
// When the number of data points is odd, the middle value is returned.
// When it is even, the larger of the two middle values is returned.
//
// >>> median_high([1, 3, 5])
// 3
// >>> median_high([1, 3, 5, 7])
// 5
//
//go:linkname MedianHigh py.median_high
func MedianHigh(data *py.Object) *py.Object
// Estimates the median for numeric data binned around the midpoints
//
// of consecutive, fixed-width intervals.
//
// The *data* can be any iterable of numeric data with each value being
// exactly the midpoint of a bin. At least one value must be present.
//
// The *interval* is width of each bin.
//
// For example, demographic information may have been summarized into
// consecutive ten-year age groups with each group being represented
// by the 5-year midpoints of the intervals:
//
// >>> demographics = Counter({
// ... 25: 172, # 20 to 30 years old
// ... 35: 484, # 30 to 40 years old
// ... 45: 387, # 40 to 50 years old
// ... 55: 22, # 50 to 60 years old
// ... 65: 6, # 60 to 70 years old
// ... })
//
// The 50th percentile (median) is the 536th person out of the 1071
// member cohort. That person is in the 30 to 40 year old age group.
//
// The regular median() function would assume that everyone in the
// tricenarian age group was exactly 35 years old. A more tenable
// assumption is that the 484 members of that age group are evenly
// distributed between 30 and 40. For that, we use median_grouped().
//
// >>> data = list(demographics.elements())
// >>> median(data)
// 35
// >>> round(median_grouped(data, interval=10), 1)
// 37.5
//
// The caller is responsible for making sure the data points are separated
// by exact multiples of *interval*. This is essential for getting a
// correct result. The function does not check this precondition.
//
// Inputs may be any numeric type that can be coerced to a float during
// the interpolation step.
//
//go:linkname MedianGrouped py.median_grouped
func MedianGrouped(data *py.Object, interval *py.Object) *py.Object
// Return the most common data point from discrete or nominal data.
//
// ``mode`` assumes discrete data, and returns a single value. This is the
// standard treatment of the mode as commonly taught in schools:
//
// >>> mode([1, 1, 2, 3, 3, 3, 3, 4])
// 3
//
// This also works with nominal (non-numeric) data:
//
// >>> mode(["red", "blue", "blue", "red", "green", "red", "red"])
// 'red'
//
// If there are multiple modes with same frequency, return the first one
// encountered:
//
// >>> mode(['red', 'red', 'green', 'blue', 'blue'])
// 'red'
//
// If *data* is empty, ``mode``, raises StatisticsError.
//
//go:linkname Mode py.mode
func Mode(data *py.Object) *py.Object
// Return a list of the most frequently occurring values.
//
// Will return more than one result if there are multiple modes
// or an empty list if *data* is empty.
//
// >>> multimode('aabbbbbbbbcc')
// ['b']
// >>> multimode('aabbbbccddddeeffffgg')
// ['b', 'd', 'f']
// >>> multimode('')
// []
//
//go:linkname Multimode py.multimode
func Multimode(data *py.Object) *py.Object
// Divide *data* into *n* continuous intervals with equal probability.
//
// Returns a list of (n - 1) cut points separating the intervals.
//
// Set *n* to 4 for quartiles (the default). Set *n* to 10 for deciles.
// Set *n* to 100 for percentiles which gives the 99 cuts points that
// separate *data* in to 100 equal sized groups.
//
// The *data* can be any iterable containing sample.
// The cut points are linearly interpolated between data points.
//
// If *method* is set to *inclusive*, *data* is treated as population
// data. The minimum value is treated as the 0th percentile and the
// maximum value is treated as the 100th percentile.
//
//go:linkname Quantiles py.quantiles
func Quantiles(data *py.Object) *py.Object
// Return the sample variance of data.
//
// data should be an iterable of Real-valued numbers, with at least two
// values. The optional argument xbar, if given, should be the mean of
// the data. If it is missing or None, the mean is automatically calculated.
//
// Use this function when your data is a sample from a population. To
// calculate the variance from the entire population, see ``pvariance``.
//
// Examples:
//
// >>> data = [2.75, 1.75, 1.25, 0.25, 0.5, 1.25, 3.5]
// >>> variance(data)
// 1.3720238095238095
//
// If you have already calculated the mean of your data, you can pass it as
// the optional second argument ``xbar`` to avoid recalculating it:
//
// >>> m = mean(data)
// >>> variance(data, m)
// 1.3720238095238095
//
// This function does not check that ``xbar`` is actually the mean of
// ``data``. Giving arbitrary values for ``xbar`` may lead to invalid or
// impossible results.
//
// Decimals and Fractions are supported:
//
// >>> from decimal import Decimal as D
// >>> variance([D("27.5"), D("30.25"), D("30.25"), D("34.5"), D("41.75")])
// Decimal('31.01875')
//
// >>> from fractions import Fraction as F
// >>> variance([F(1, 6), F(1, 2), F(5, 3)])
// Fraction(67, 108)
//
//go:linkname Variance py.variance
func Variance(data *py.Object, xbar *py.Object) *py.Object
// Return the population variance of “data“.
//
// data should be a sequence or iterable of Real-valued numbers, with at least one
// value. The optional argument mu, if given, should be the mean of
// the data. If it is missing or None, the mean is automatically calculated.
//
// Use this function to calculate the variance from the entire population.
// To estimate the variance from a sample, the ``variance`` function is
// usually a better choice.
//
// Examples:
//
// >>> data = [0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25]
// >>> pvariance(data)
// 1.25
//
// If you have already calculated the mean of the data, you can pass it as
// the optional second argument to avoid recalculating it:
//
// >>> mu = mean(data)
// >>> pvariance(data, mu)
// 1.25
//
// Decimals and Fractions are supported:
//
// >>> from decimal import Decimal as D
// >>> pvariance([D("27.5"), D("30.25"), D("30.25"), D("34.5"), D("41.75")])
// Decimal('24.815')
//
// >>> from fractions import Fraction as F
// >>> pvariance([F(1, 4), F(5, 4), F(1, 2)])
// Fraction(13, 72)
//
//go:linkname Pvariance py.pvariance
func Pvariance(data *py.Object, mu *py.Object) *py.Object
// Return the square root of the sample variance.
//
// See ``variance`` for arguments and other details.
//
// >>> stdev([1.5, 2.5, 2.5, 2.75, 3.25, 4.75])
// 1.0810874155219827
//
//go:linkname Stdev py.stdev
func Stdev(data *py.Object, xbar *py.Object) *py.Object
// Return the square root of the population variance.
//
// See ``pvariance`` for arguments and other details.
//
// >>> pstdev([1.5, 2.5, 2.5, 2.75, 3.25, 4.75])
// 0.986893273527251
//
//go:linkname Pstdev py.pstdev
func Pstdev(data *py.Object, mu *py.Object) *py.Object
// Covariance
//
// Return the sample covariance of two inputs *x* and *y*. Covariance
// is a measure of the joint variability of two inputs.
//
// >>> x = [1, 2, 3, 4, 5, 6, 7, 8, 9]
// >>> y = [1, 2, 3, 1, 2, 3, 1, 2, 3]
// >>> covariance(x, y)
// 0.75
// >>> z = [9, 8, 7, 6, 5, 4, 3, 2, 1]
// >>> covariance(x, z)
// -7.5
// >>> covariance(z, x)
// -7.5
//
//go:linkname Covariance py.covariance
func Covariance(x *py.Object, y *py.Object) *py.Object
// Pearson's correlation coefficient
//
// Return the Pearson's correlation coefficient for two inputs. Pearson's
// correlation coefficient *r* takes values between -1 and +1. It measures
// the strength and direction of a linear relationship.
//
// >>> x = [1, 2, 3, 4, 5, 6, 7, 8, 9]
// >>> y = [9, 8, 7, 6, 5, 4, 3, 2, 1]
// >>> correlation(x, x)
// 1.0
// >>> correlation(x, y)
// -1.0
//
// If *method* is "ranked", computes Spearman's rank correlation coefficient
// for two inputs. The data is replaced by ranks. Ties are averaged
// so that equal values receive the same rank. The resulting coefficient
// measures the strength of a monotonic relationship.
//
// Spearman's rank correlation coefficient is appropriate for ordinal
// data or for continuous data that doesn't meet the linear proportion
// requirement for Pearson's correlation coefficient.
//
//go:linkname Correlation py.correlation
func Correlation(x *py.Object, y *py.Object) *py.Object
// Slope and intercept for simple linear regression.
//
// Return the slope and intercept of simple linear regression
// parameters estimated using ordinary least squares. Simple linear
// regression describes relationship between an independent variable
// *x* and a dependent variable *y* in terms of a linear function:
//
// y = slope * x + intercept + noise
//
// where *slope* and *intercept* are the regression parameters that are
// estimated, and noise represents the variability of the data that was
// not explained by the linear regression (it is equal to the
// difference between predicted and actual values of the dependent
// variable).
//
// The parameters are returned as a named tuple.
//
// >>> x = [1, 2, 3, 4, 5]
// >>> noise = NormalDist().samples(5, seed=42)
// >>> y = [3 * x[i] + 2 + noise[i] for i in range(5)]
// >>> linear_regression(x, y) #doctest: +ELLIPSIS
// LinearRegression(slope=3.09078914170..., intercept=1.75684970486...)
//
// If *proportional* is true, the independent variable *x* and the
// dependent variable *y* are assumed to be directly proportional.
// The data is fit to a line passing through the origin.
//
// Since the *intercept* will always be 0.0, the underlying linear
// function simplifies to:
//
// y = slope * x + noise
//
// >>> y = [3 * x[i] + noise[i] for i in range(5)]
// >>> linear_regression(x, y, proportional=True) #doctest: +ELLIPSIS
// LinearRegression(slope=3.02447542484..., intercept=0.0)
//
//go:linkname LinearRegression py.linear_regression
func LinearRegression(x *py.Object, y *py.Object) *py.Object

Binary file not shown.

220
py/sys/gen.go Normal file
View File

@@ -0,0 +1,220 @@
package sys
import (
_ "unsafe"
"github.com/goplus/llgo/py"
)
const LLGoPackage = "py.sys"
// Adds a new audit hook callback.
//
//go:linkname Addaudithook py.addaudithook
func Addaudithook(hook *py.Object) *py.Object
// Print an object to sys.stdout and also save it in builtins._
//
//go:linkname Displayhook py.displayhook
func Displayhook(object *py.Object) *py.Object
// Return the current exception.
//
// Return the most recent exception caught by an except clause
// in the current stack frame or in an older stack frame, or None
// if no such exception exists.
//
//go:linkname Exception py.exception
func Exception() *py.Object
// Return current exception information: (type, value, traceback).
//
// Return information about the most recent exception caught by an except
// clause in the current stack frame or in an older stack frame.
//
//go:linkname ExcInfo py.exc_info
func ExcInfo() *py.Object
// Handle an exception by displaying it with a traceback on sys.stderr.
//
//go:linkname Excepthook py.excepthook
func Excepthook(exctype *py.Object, value *py.Object, traceback *py.Object) *py.Object
// Exit the interpreter by raising SystemExit(status).
//
// If the status is omitted or None, it defaults to zero (i.e., success).
// If the status is an integer, it will be used as the system exit status.
// If it is another kind of object, it will be printed and the system
// exit status will be one (i.e., failure).
//
//go:linkname Exit py.exit
func Exit(status *py.Object) *py.Object
// Return the current default encoding used by the Unicode implementation.
//
//go:linkname Getdefaultencoding py.getdefaultencoding
func Getdefaultencoding() *py.Object
// Return the current value of the flags that are used for dlopen calls.
//
// The flag constants are defined in the os module.
//
//go:linkname Getdlopenflags py.getdlopenflags
func Getdlopenflags() *py.Object
// Return the number of memory blocks currently allocated.
//
//go:linkname Getallocatedblocks py.getallocatedblocks
func Getallocatedblocks() *py.Object
// Return the number of elements of the unicode interned dictionary
//
//go:linkname Getunicodeinternedsize py.getunicodeinternedsize
func Getunicodeinternedsize() *py.Object
// Return the encoding used to convert Unicode filenames to OS filenames.
//
//go:linkname Getfilesystemencoding py.getfilesystemencoding
func Getfilesystemencoding() *py.Object
// Return the error mode used Unicode to OS filename conversion.
//
//go:linkname Getfilesystemencodeerrors py.getfilesystemencodeerrors
func Getfilesystemencodeerrors() *py.Object
// Return the reference count of object.
//
// The count returned is generally one higher than you might expect,
// because it includes the (temporary) reference as an argument to
// getrefcount().
//
//go:linkname Getrefcount py.getrefcount
func Getrefcount(object *py.Object) *py.Object
// Return the current value of the recursion limit.
//
// The recursion limit is the maximum depth of the Python interpreter
// stack. This limit prevents infinite recursion from causing an overflow
// of the C stack and crashing Python.
//
//go:linkname Getrecursionlimit py.getrecursionlimit
func Getrecursionlimit() *py.Object
// “Intern” the given string.
//
// This enters the string in the (global) table of interned strings whose
// purpose is to speed up dictionary lookups. Return the string itself or
// the previously interned string object with the same value.
//
//go:linkname Intern py.intern
func Intern(string *py.Object) *py.Object
// Return True if Python is exiting.
//
//go:linkname IsFinalizing py.is_finalizing
func IsFinalizing() *py.Object
// Set the ideal thread switching delay inside the Python interpreter.
//
// The actual frequency of switching threads can be lower if the
// interpreter executes long sequences of uninterruptible code
// (this is implementation-specific and workload-dependent).
//
// The parameter must represent the desired switching delay in seconds
// A typical value is 0.005 (5 milliseconds).
//
//go:linkname Setswitchinterval py.setswitchinterval
func Setswitchinterval(interval *py.Object) *py.Object
// Return the current thread switch interval; see sys.setswitchinterval().
//
//go:linkname Getswitchinterval py.getswitchinterval
func Getswitchinterval() *py.Object
// Set the flags used by the interpreter for dlopen calls.
//
// This is used, for example, when the interpreter loads extension
// modules. Among other things, this will enable a lazy resolving of
// symbols when importing a module, if called as sys.setdlopenflags(0).
// To share symbols across extension modules, call as
// sys.setdlopenflags(os.RTLD_GLOBAL). Symbolic names for the flag
// modules can be found in the os module (RTLD_xxx constants, e.g.
// os.RTLD_LAZY).
//
//go:linkname Setdlopenflags py.setdlopenflags
func Setdlopenflags(flags *py.Object) *py.Object
// Set the maximum depth of the Python interpreter stack to n.
//
// This limit prevents infinite recursion from causing an overflow of the C
// stack and crashing Python. The highest possible limit is platform-
// dependent.
//
//go:linkname Setrecursionlimit py.setrecursionlimit
func Setrecursionlimit(limit *py.Object) *py.Object
// Return the global debug tracing function set with sys.settrace.
//
// See the debugger chapter in the library manual.
//
//go:linkname Gettrace py.gettrace
func Gettrace() *py.Object
// Call func(*args), while tracing is enabled.
//
// The tracing state is saved, and restored afterwards. This is intended
// to be called from a debugger from a checkpoint, to recursively debug
// some other code.
//
//go:linkname CallTracing py.call_tracing
func CallTracing(func_ *py.Object, args *py.Object) *py.Object
// Enable or disable origin tracking for coroutine objects in this thread.
//
// Coroutine objects will track 'depth' frames of traceback information
// about where they came from, available in their cr_origin attribute.
//
// Set a depth of 0 to disable.
//
//go:linkname SetCoroutineOriginTrackingDepth py.set_coroutine_origin_tracking_depth
func SetCoroutineOriginTrackingDepth(depth *py.Object) *py.Object
// Check status of origin tracking for coroutine objects in this thread.
//
//go:linkname GetCoroutineOriginTrackingDepth py.get_coroutine_origin_tracking_depth
func GetCoroutineOriginTrackingDepth() *py.Object
// Deactivate the current stack profiler trampoline backend.
//
// If no stack profiler is activated, this function has no effect.
//
//go:linkname DeactivateStackTrampoline py.deactivate_stack_trampoline
func DeactivateStackTrampoline() *py.Object
// Return *True* if a stack profiler trampoline is active.
//
//go:linkname IsStackTrampolineActive py.is_stack_trampoline_active
func IsStackTrampolineActive() *py.Object
// Handle an unraisable exception.
//
// The unraisable argument has the following attributes:
//
// * exc_type: Exception type.
// * exc_value: Exception value, can be None.
// * exc_traceback: Exception traceback, can be None.
// * err_msg: Error message, can be None.
// * object: Object causing the exception, can be None.
//
//go:linkname Unraisablehook py.unraisablehook
func Unraisablehook(unraisable *py.Object) *py.Object
// Return the maximum string digits limit for non-binary int<->str conversions.
//
//go:linkname GetIntMaxStrDigits py.get_int_max_str_digits
func GetIntMaxStrDigits() *py.Object
// Set the maximum string digits limit for non-binary int<->str conversions.
//
//go:linkname SetIntMaxStrDigits py.set_int_max_str_digits
func SetIntMaxStrDigits(maxdigits *py.Object) *py.Object

BIN
py/sys/llgo_autogen.lla Normal file

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More