Compare commits
78 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a35ffcc27 | ||
|
|
5eae8f9af6 | ||
|
|
25381e20d2 | ||
|
|
fc35ff5cd1 | ||
|
|
b10d00b426 | ||
|
|
c634dc25b4 | ||
|
|
2fb4561bf8 | ||
|
|
f167c6dcca | ||
|
|
555ace9e2e | ||
|
|
d07ffb36ad | ||
|
|
9e2b8b77c9 | ||
|
|
29e4af4fb2 | ||
|
|
91513a12b4 | ||
|
|
ee3f55dd41 | ||
|
|
c2e5a78076 | ||
|
|
da3ac3e93d | ||
|
|
278ebbc9bd | ||
|
|
546f93147e | ||
|
|
3e7bfbb45c | ||
|
|
c2cf0443ef | ||
|
|
59d68c6438 | ||
|
|
e0ee199bf1 | ||
|
|
c1bf895674 | ||
|
|
ea4d92e671 | ||
|
|
e3f56105d4 | ||
|
|
c447a87605 | ||
|
|
584e5b1f01 | ||
|
|
207dc4c112 | ||
|
|
6a3581f7a3 | ||
|
|
11e74975b3 | ||
|
|
75ef9ec524 | ||
|
|
9b742e777b | ||
|
|
5d93565e16 | ||
|
|
cebfe5c95b | ||
|
|
7881f3a53b | ||
|
|
56269bd52b | ||
|
|
68c43a2cc9 | ||
|
|
120b507c75 | ||
|
|
44fe7e8dc4 | ||
|
|
75d679f141 | ||
|
|
e9570f2400 | ||
|
|
5b8567310c | ||
|
|
f882221db3 | ||
|
|
8c4d7bd641 | ||
|
|
6a78695fde | ||
|
|
73ad16dedd | ||
|
|
dd98112c5a | ||
|
|
47521d3579 | ||
|
|
0c31300578 | ||
|
|
6340ff7da0 | ||
|
|
b66cb49d80 | ||
|
|
c884184220 | ||
|
|
091fee61e0 | ||
|
|
172a268e77 | ||
|
|
924715fe34 | ||
|
|
35a73b4cde | ||
|
|
238f9593f9 | ||
|
|
9e8b5703dc | ||
|
|
d8bd8be57e | ||
|
|
a4d4e8b3a9 | ||
|
|
703dd17e33 | ||
|
|
bc654a462e | ||
|
|
11535825c0 | ||
|
|
196df40c99 | ||
|
|
7aee6c3a15 | ||
|
|
372b566d23 | ||
|
|
9550354442 | ||
|
|
95c3ddfc39 | ||
|
|
bf4f2b6fa0 | ||
|
|
d3f75a92ad | ||
|
|
369495c8d3 | ||
|
|
dd52f71069 | ||
|
|
af8e2bc19d | ||
|
|
947e5591ea | ||
|
|
521376e8e8 | ||
|
|
55c0adb23d | ||
|
|
b20ad7047f | ||
|
|
fa3149c660 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -13,6 +13,7 @@ llgo_autogen.ll
|
|||||||
stories*.bin
|
stories*.bin
|
||||||
.DS_Store
|
.DS_Store
|
||||||
err.log
|
err.log
|
||||||
|
numpy.txt
|
||||||
|
|
||||||
_go/
|
_go/
|
||||||
_runtime/
|
_runtime/
|
||||||
|
|||||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,6 +1,3 @@
|
|||||||
[submodule "x/llama2/llama2.c"]
|
[submodule "x/llama2/llama2.c"]
|
||||||
path = x/llama2/llama2.c
|
path = x/llama2/llama2.c
|
||||||
url = https://github.com/karpathy/llama2.c.git
|
url = https://github.com/karpathy/llama2.c.git
|
||||||
[submodule "x/sqlite/sqlite"]
|
|
||||||
path = x/sqlite/sqlite
|
|
||||||
url = https://github.com/sqlite/sqlite.git
|
|
||||||
|
|||||||
188
README.md
188
README.md
@@ -8,7 +8,8 @@ llgo - A Go compiler based on LLVM
|
|||||||
[](https://pkg.go.dev/github.com/goplus/llgo)
|
[](https://pkg.go.dev/github.com/goplus/llgo)
|
||||||
[](https://github.com/goplus/gop)
|
[](https://github.com/goplus/gop)
|
||||||
|
|
||||||
This 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).
|
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
|
## C standard libary support
|
||||||
|
|
||||||
@@ -22,14 +23,40 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
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.
|
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.
|
See [github.com/goplus/llgo/c](https://pkg.go.dev/github.com/goplus/llgo/c) for more detials.
|
||||||
|
|
||||||
|
|
||||||
## Python support
|
## Python support
|
||||||
|
|
||||||
You can import a Python library in llgo! For example:
|
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
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -46,12 +73,119 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Here, We call `py.Float(2)` to create a Python floating point number 2, and pass it to Python’s `math.sqrt` to get `x`. Then use `x.Float64()` to convert the Python object to Go's `float64` type, and finally we print the value through C `printf`.
|
Here, We call `py.Float(2)` to create a Python number 2, and pass it to Python’s `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
|
## Other frequently used libraries
|
||||||
|
|
||||||
TODO
|
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
|
## How to install
|
||||||
@@ -79,47 +213,3 @@ go install -v ./...
|
|||||||
### on Windows
|
### on Windows
|
||||||
|
|
||||||
TODO
|
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)
|
|
||||||
|
|
||||||
And the `_pydemo` directory contains python related demos:
|
|
||||||
|
|
||||||
* [callpy](_pydemo/callpy/callpy.go): call Python standard library function `math.sqrt`
|
|
||||||
|
|
||||||
|
|
||||||
### How to run demos
|
|
||||||
|
|
||||||
To run the demos in directory `_demo`:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cd <demo-directory> # eg. cd _demo/genints
|
|
||||||
llgo run .
|
|
||||||
```
|
|
||||||
|
|
||||||
To run the demos in directory `_pydemo`, 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 `_pydemo`:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cd <demo-directory> # eg. cd _pydemo/callpy
|
|
||||||
llgo run .
|
|
||||||
```
|
|
||||||
|
|||||||
22
_pydemo/matrix/matrix.go
Normal file
22
_pydemo/matrix/matrix.go
Normal 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
10
_pydemo/pi/pi.go
Normal 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())
|
||||||
|
}
|
||||||
13
_pydemo/statistics/statistics.go
Normal file
13
_pydemo/statistics/statistics.go
Normal 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())
|
||||||
|
}
|
||||||
4
c/c.go
4
c/c.go
@@ -28,6 +28,10 @@ type (
|
|||||||
Char = int8
|
Char = int8
|
||||||
Int = C.int
|
Int = C.int
|
||||||
Uint = C.uint
|
Uint = C.uint
|
||||||
|
Long = int32
|
||||||
|
Ulong = uint32
|
||||||
|
LongLong = int64
|
||||||
|
UlongLong = uint64
|
||||||
Float = float32
|
Float = float32
|
||||||
Pointer = unsafe.Pointer
|
Pointer = unsafe.Pointer
|
||||||
FilePtr = unsafe.Pointer
|
FilePtr = unsafe.Pointer
|
||||||
|
|||||||
60
chore/_xtool/pydump/pydump.go
Normal file
60
chore/_xtool/pydump/pydump.go
Normal 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())
|
||||||
|
}
|
||||||
200
chore/llpyg/llpyg.go
Normal file
200
chore/llpyg/llpyg.go
Normal 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: "//"}
|
||||||
|
)
|
||||||
@@ -51,7 +51,7 @@ _llgo_0:
|
|||||||
|
|
||||||
define void @main.gwrite(%"github.com/goplus/llgo/internal/runtime.Slice" %0) {
|
define void @main.gwrite(%"github.com/goplus/llgo/internal/runtime.Slice" %0) {
|
||||||
_llgo_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
|
%2 = icmp eq i64 %1, 0
|
||||||
br i1 %2, label %_llgo_1, label %_llgo_2
|
br i1 %2, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
@@ -680,7 +680,7 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
|
|
||||||
define void @main.println(%"github.com/goplus/llgo/internal/runtime.Slice" %0) {
|
define void @main.println(%"github.com/goplus/llgo/internal/runtime.Slice" %0) {
|
||||||
_llgo_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
|
br label %_llgo_1
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_5, %_llgo_0
|
_llgo_1: ; preds = %_llgo_5, %_llgo_0
|
||||||
@@ -690,7 +690,7 @@ _llgo_1: ; preds = %_llgo_5, %_llgo_0
|
|||||||
br i1 %4, label %_llgo_2, label %_llgo_3
|
br i1 %4, label %_llgo_2, label %_llgo_3
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_1
|
_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
|
%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
|
%7 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %6, align 8
|
||||||
%8 = icmp ne i64 %3, 0
|
%8 = icmp ne i64 %3, 0
|
||||||
@@ -783,8 +783,6 @@ _llgo_0:
|
|||||||
|
|
||||||
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
|
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 i32 @printf(ptr, ...)
|
||||||
|
|
||||||
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
@@ -802,5 +800,3 @@ declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llg
|
|||||||
declare { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface", ptr)
|
declare { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"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)
|
declare { %"github.com/goplus/llgo/internal/runtime.String", i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2String"(%"github.com/goplus/llgo/internal/runtime.iface", ptr)
|
||||||
|
|
||||||
declare ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice")
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ _llgo_0:
|
|||||||
|
|
||||||
define void @main.test(%"github.com/goplus/llgo/internal/runtime.Slice" %0) {
|
define void @main.test(%"github.com/goplus/llgo/internal/runtime.Slice" %0) {
|
||||||
_llgo_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
|
br label %_llgo_1
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_2, %_llgo_0
|
_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
|
br i1 %4, label %_llgo_2, label %_llgo_3
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_1
|
_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
|
%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
|
%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)
|
%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 %"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 i64 @"github.com/goplus/llgo/internal/runtime.I2Int"(%"github.com/goplus/llgo/internal/runtime.iface", ptr)
|
||||||
|
|
||||||
declare i32 @printf(ptr, ...)
|
declare i32 @printf(ptr, ...)
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ _llgo_0:
|
|||||||
%6 = call ptr @PyObject_CallNoArgs(ptr %5)
|
%6 = call ptr @PyObject_CallNoArgs(ptr %5)
|
||||||
%7 = call double @PyFloat_AsDouble(ptr %4)
|
%7 = call double @PyFloat_AsDouble(ptr %4)
|
||||||
%8 = call i32 (ptr, ...) @printf(ptr @0, double %7)
|
%8 = call i32 (ptr, ...) @printf(ptr @0, double %7)
|
||||||
%9 = call ptr @PyBytes_AsString(ptr %6)
|
%9 = call ptr @PyUnicode_AsUTF8(ptr %6)
|
||||||
%10 = call i32 (ptr, ...) @printf(ptr @1, ptr %9)
|
%10 = call i32 (ptr, ...) @printf(ptr @1, ptr %9)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
@@ -67,7 +67,7 @@ declare double @PyFloat_AsDouble(ptr)
|
|||||||
|
|
||||||
declare i32 @printf(ptr, ...)
|
declare i32 @printf(ptr, ...)
|
||||||
|
|
||||||
declare ptr @PyBytes_AsString(ptr)
|
declare ptr @PyUnicode_AsUTF8(ptr)
|
||||||
|
|
||||||
declare void @llgoLoadPyModSyms(ptr, ...)
|
declare void @llgoLoadPyModSyms(ptr, ...)
|
||||||
|
|
||||||
|
|||||||
12
cl/_testpy/gcd/in.go
Normal file
12
cl/_testpy/gcd/in.go
Normal 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
59
cl/_testpy/gcd/out.ll
Normal 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()
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
; ModuleID = 'math'
|
; ModuleID = 'math'
|
||||||
source_filename = "math"
|
source_filename = "math"
|
||||||
|
|
||||||
@__llgo_py.math.sqrt = external global ptr
|
|
||||||
@"math.init$guard" = global ptr null
|
@"math.init$guard" = global ptr null
|
||||||
@__llgo_py.math = linkonce global ptr null
|
@__llgo_py.math = linkonce global ptr null
|
||||||
@0 = private unnamed_addr constant [5 x i8] c"math\00", align 1
|
@0 = private unnamed_addr constant [5 x i8] c"math\00", align 1
|
||||||
|
|||||||
24
cl/_testpy/matrix/in.go
Normal file
24
cl/_testpy/matrix/in.go
Normal 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
121
cl/_testpy/matrix/out.ll
Normal 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
10
cl/_testpy/pi/in.go
Normal 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
49
cl/_testpy/pi/out.ll
Normal 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
12
cl/_testpy/pow/in.go
Normal 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
58
cl/_testpy/pow/out.ll
Normal 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()
|
||||||
@@ -40,6 +40,12 @@ func main() {
|
|||||||
string_len("hello"[1:])
|
string_len("hello"[1:])
|
||||||
string_len("hello"[1:2])
|
string_len("hello"[1:2])
|
||||||
string_len("hello"[5:])
|
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) {
|
func string_len(s string) {
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ source_filename = "main"
|
|||||||
@1 = private unnamed_addr constant [6 x i8] c"hello\00", align 1
|
@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
|
@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
|
@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() {
|
define void @main.init() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
@@ -57,7 +58,7 @@ _llgo_0:
|
|||||||
store i64 2, ptr %10, align 4
|
store i64 2, ptr %10, align 4
|
||||||
store i64 3, ptr %11, align 4
|
store i64 3, ptr %11, align 4
|
||||||
store i64 4, ptr %12, 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)
|
call void @main.out(i64 %13)
|
||||||
%14 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
|
%14 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
|
||||||
%15 = getelementptr inbounds i64, ptr %14, i64 0
|
%15 = getelementptr inbounds i64, ptr %14, i64 0
|
||||||
@@ -69,64 +70,64 @@ _llgo_0:
|
|||||||
%18 = getelementptr inbounds i64, ptr %14, i64 3
|
%18 = getelementptr inbounds i64, ptr %14, i64 3
|
||||||
store i64 4, ptr %18, align 4
|
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)
|
%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 %20)
|
||||||
call void @main.out(i64 4)
|
call void @main.out(i64 4)
|
||||||
call void @main.out(i64 4)
|
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 %21)
|
||||||
call void @main.out(i64 4)
|
call void @main.out(i64 4)
|
||||||
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)
|
%22 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 2
|
||||||
%23 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
%23 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 2
|
||||||
%24 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
%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)
|
%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)
|
call void @main.out(i64 %26)
|
||||||
%27 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
%27 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 2
|
||||||
%28 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
%28 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 2
|
||||||
%29 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
%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)
|
%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)
|
call void @main.out(i64 %31)
|
||||||
%32 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
%32 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 2
|
||||||
%33 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
%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)
|
%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)
|
call void @main.out(i64 %35)
|
||||||
%36 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
%36 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 2
|
||||||
%37 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
%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)
|
%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)
|
call void @main.out(i64 %39)
|
||||||
%40 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
%40 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 2
|
||||||
%41 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
%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)
|
%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)
|
call void @main.out(i64 %43)
|
||||||
%44 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
%44 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 2
|
||||||
%45 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
%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)
|
%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)
|
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)
|
%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)
|
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)
|
%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)
|
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)
|
%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)
|
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)
|
%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)
|
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)
|
%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)
|
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)
|
%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)
|
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)
|
%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)
|
call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %60)
|
||||||
@@ -141,12 +142,41 @@ _llgo_0:
|
|||||||
%67 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %66, 1
|
%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)
|
%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)
|
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
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main.out(i64 %0) {
|
define void @main.out(i64 %0) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%1 = call i32 (ptr, ...) @printf(ptr @4, i64 %0)
|
%1 = call i32 (ptr, ...) @printf(ptr @5, i64 %0)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,14 +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 %"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 %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64)
|
||||||
|
|
||||||
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.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, ...)
|
declare i32 @printf(ptr, ...)
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ func concat(args ...string) (ret string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func info(s string) string {
|
||||||
|
return "" + s + "..."
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
result := concat("Hello", " ", "World")
|
result := concat("Hello", " ", "World")
|
||||||
c.Fprintf(c.Stderr, c.Str("Hi, %s\n"), c.AllocaCStr(result))
|
c.Fprintf(c.Stderr, c.Str("Hi, %s\n"), c.AllocaCStr(result))
|
||||||
|
|||||||
@@ -6,17 +6,19 @@ source_filename = "main"
|
|||||||
|
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
@0 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
|
@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_argc = global ptr null
|
||||||
@__llgo_argv = global ptr null
|
@__llgo_argv = global ptr null
|
||||||
@1 = 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
|
||||||
@2 = private unnamed_addr constant [2 x i8] c" \00", align 1
|
@4 = private unnamed_addr constant [2 x i8] c" \00", align 1
|
||||||
@3 = private unnamed_addr constant [6 x i8] c"World\00", align 1
|
@5 = private unnamed_addr constant [6 x i8] c"World\00", align 1
|
||||||
@__stderrp = external global ptr
|
@__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) {
|
define %"github.com/goplus/llgo/internal/runtime.String" @main.concat(%"github.com/goplus/llgo/internal/runtime.Slice" %0) {
|
||||||
_llgo_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)
|
%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
|
%3 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %2, 0
|
||||||
%4 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %2, 1
|
%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
|
br i1 %13, label %_llgo_2, label %_llgo_3
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_1
|
_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
|
%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
|
%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)
|
%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
|
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() {
|
define void @main.init() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%0 = load i1, ptr @"main.init$guard", align 1
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
@@ -70,13 +81,13 @@ _llgo_0:
|
|||||||
call void @main.init()
|
call void @main.init()
|
||||||
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 48)
|
%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
|
%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
|
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
|
%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
|
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
|
%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
|
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)
|
%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)
|
%10 = call %"github.com/goplus/llgo/internal/runtime.String" @main.concat(%"github.com/goplus/llgo/internal/runtime.Slice" %9)
|
||||||
@@ -85,14 +96,10 @@ _llgo_0:
|
|||||||
%13 = add i64 %12, 1
|
%13 = add i64 %12, 1
|
||||||
%14 = alloca i8, i64 %13, align 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)
|
%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
|
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.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)
|
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ _llgo_0:
|
|||||||
%2 = mul i64 %0, 4
|
%2 = mul i64 %0, 4
|
||||||
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 %2)
|
%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)
|
%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
|
br label %_llgo_1
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_2, %_llgo_0
|
_llgo_1: ; preds = %_llgo_2, %_llgo_0
|
||||||
@@ -29,7 +29,7 @@ _llgo_2: ; preds = %_llgo_1
|
|||||||
%9 = extractvalue { ptr, ptr } %1, 1
|
%9 = extractvalue { ptr, ptr } %1, 1
|
||||||
%10 = extractvalue { ptr, ptr } %1, 0
|
%10 = extractvalue { ptr, ptr } %1, 0
|
||||||
%11 = call i32 %10(ptr %9)
|
%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
|
%13 = getelementptr inbounds i32, ptr %12, i64 %7
|
||||||
store i32 %11, ptr %13, align 4
|
store i32 %11, ptr %13, align 4
|
||||||
br label %_llgo_1
|
br label %_llgo_1
|
||||||
@@ -76,7 +76,7 @@ _llgo_0:
|
|||||||
store ptr null, ptr %4, align 8
|
store ptr null, ptr %4, align 8
|
||||||
%5 = load { ptr, ptr }, ptr %2, 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)
|
%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
|
br label %_llgo_1
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_2, %_llgo_0
|
_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
|
br i1 %10, label %_llgo_2, label %_llgo_3
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_1
|
_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
|
%12 = getelementptr inbounds i32, ptr %11, i64 %9
|
||||||
%13 = load i32, ptr %12, align 4
|
%13 = load i32, ptr %12, align 4
|
||||||
%14 = call i32 (ptr, ...) @printf(ptr @0, i32 %13)
|
%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
|
store ptr %16, ptr %20, align 8
|
||||||
%21 = load { ptr, ptr }, ptr %18, 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)
|
%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
|
br label %_llgo_4
|
||||||
|
|
||||||
_llgo_4: ; preds = %_llgo_5, %_llgo_3
|
_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
|
br i1 %26, label %_llgo_5, label %_llgo_6
|
||||||
|
|
||||||
_llgo_5: ; preds = %_llgo_4
|
_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
|
%28 = getelementptr inbounds i32, ptr %27, i64 %25
|
||||||
%29 = load i32, ptr %28, align 4
|
%29 = load i32, ptr %28, align 4
|
||||||
%30 = call i32 (ptr, ...) @printf(ptr @1, i32 %29)
|
%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
|
store ptr %33, ptr %37, align 8
|
||||||
%38 = load { ptr, ptr }, ptr %35, 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)
|
%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
|
br label %_llgo_7
|
||||||
|
|
||||||
_llgo_7: ; preds = %_llgo_8, %_llgo_6
|
_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
|
br i1 %43, label %_llgo_8, label %_llgo_9
|
||||||
|
|
||||||
_llgo_8: ; preds = %_llgo_7
|
_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
|
%45 = getelementptr inbounds i32, ptr %44, i64 %42
|
||||||
%46 = load i32, ptr %45, align 4
|
%46 = load i32, ptr %45, align 4
|
||||||
%47 = call i32 (ptr, ...) @printf(ptr @2, i32 %46)
|
%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 %"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 void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
declare i32 @rand()
|
declare i32 @rand()
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ _llgo_0:
|
|||||||
|
|
||||||
define i64 @main.sum(%"github.com/goplus/llgo/internal/runtime.Slice" %0) {
|
define i64 @main.sum(%"github.com/goplus/llgo/internal/runtime.Slice" %0) {
|
||||||
_llgo_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
|
br label %_llgo_1
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_2, %_llgo_0
|
_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
|
br i1 %5, label %_llgo_2, label %_llgo_3
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_1
|
_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
|
%7 = getelementptr inbounds i64, ptr %6, i64 %4
|
||||||
%8 = load i64, ptr %7, align 4
|
%8 = load i64, ptr %7, align 4
|
||||||
%9 = add i64 %2, %8
|
%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 %"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 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")
|
|
||||||
|
|||||||
@@ -226,5 +226,5 @@ func TestErrVarOf(t *testing.T) {
|
|||||||
}
|
}
|
||||||
ssaPkg := &ssa.Package{Pkg: pkgTypes}
|
ssaPkg := &ssa.Package{Pkg: pkgTypes}
|
||||||
g := &ssa.Global{Pkg: ssaPkg}
|
g := &ssa.Global{Pkg: ssaPkg}
|
||||||
ctx.varOf(g)
|
ctx.varOf(nil, g)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ func (p *context) compileMethods(pkg llssa.Package, typ types.Type) {
|
|||||||
for i, n := 0, mthds.Len(); i < n; i++ {
|
for i, n := 0, mthds.Len(); i < n; i++ {
|
||||||
mthd := mthds.At(i)
|
mthd := mthds.At(i)
|
||||||
if ssaMthd := prog.MethodValue(mthd); ssaMthd != nil {
|
if ssaMthd := prog.MethodValue(mthd); ssaMthd != nil {
|
||||||
p.compileFuncDecl(pkg, ssaMthd, false)
|
p.compileFuncDecl(pkg, ssaMthd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -185,7 +185,7 @@ func (p *context) compileMethods(pkg llssa.Package, typ types.Type) {
|
|||||||
func (p *context) compileGlobal(pkg llssa.Package, gbl *ssa.Global) {
|
func (p *context) compileGlobal(pkg llssa.Package, gbl *ssa.Global) {
|
||||||
typ := gbl.Type()
|
typ := gbl.Type()
|
||||||
name, vtype := p.varName(gbl.Pkg.Pkg, gbl)
|
name, vtype := p.varName(gbl.Pkg.Pkg, gbl)
|
||||||
if ignoreName(name) || checkCgo(gbl.Name()) {
|
if vtype == pyVar || ignoreName(name) || checkCgo(gbl.Name()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
@@ -211,14 +211,16 @@ var (
|
|||||||
argvTy = types.NewPointer(types.NewPointer(types.Typ[types.Int8]))
|
argvTy = types.NewPointer(types.NewPointer(types.Typ[types.Int8]))
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function, call bool) (llssa.Function, llssa.PyObjRef, int) {
|
func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Function, llssa.PyObjRef, int) {
|
||||||
pkgTypes, name, ftype := p.funcName(f, true)
|
pkgTypes, name, ftype := p.funcName(f, true)
|
||||||
if ftype != goFunc {
|
if ftype != goFunc {
|
||||||
|
/*
|
||||||
if ftype == pyFunc {
|
if ftype == pyFunc {
|
||||||
// TODO(xsw): pyMod == ""
|
// TODO(xsw): pyMod == ""
|
||||||
fnName := pysymPrefix + p.pyMod + "." + name
|
fnName := pysymPrefix + p.pyMod + "." + name
|
||||||
return nil, pkg.NewPyFunc(fnName, f.Signature, call), pyFunc
|
return nil, pkg.NewPyFunc(fnName, f.Signature, call), pyFunc
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
return nil, nil, ignoredFunc
|
return nil, nil, ignoredFunc
|
||||||
}
|
}
|
||||||
fn := pkg.FuncOf(name)
|
fn := pkg.FuncOf(name)
|
||||||
@@ -236,7 +238,7 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function, call bool)
|
|||||||
sig = llssa.FuncAddCtx(ctx, sig)
|
sig = llssa.FuncAddCtx(ctx, sig)
|
||||||
} else {
|
} else {
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Println("==> NewFunc", name, "type:", sig.Recv(), sig)
|
log.Println("==> NewFunc", name, "type:", sig.Recv(), sig, "ftype:", ftype)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if fn == nil {
|
if fn == nil {
|
||||||
@@ -291,7 +293,7 @@ func (p *context) funcOf(fn *ssa.Function) (aFn llssa.Function, pyFn llssa.PyObj
|
|||||||
pkg := p.pkg
|
pkg := p.pkg
|
||||||
fnName := pysymPrefix + mod + "." + name
|
fnName := pysymPrefix + mod + "." + name
|
||||||
if pyFn = pkg.PyObjOf(fnName); pyFn == nil {
|
if pyFn = pkg.PyObjOf(fnName); pyFn == nil {
|
||||||
pyFn = pkg.NewPyFunc(fnName, fn.Signature, true)
|
pyFn = pkg.PyNewFunc(fnName, fn.Signature, true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -310,6 +312,8 @@ func (p *context) funcOf(fn *ssa.Function) (aFn llssa.Function, pyFn llssa.PyObj
|
|||||||
ftype = llgoAllocaCStr
|
ftype = llgoAllocaCStr
|
||||||
case "stringData":
|
case "stringData":
|
||||||
ftype = llgoStringData
|
ftype = llgoStringData
|
||||||
|
case "pyList":
|
||||||
|
ftype = llgoPyList
|
||||||
case "unreachable":
|
case "unreachable":
|
||||||
ftype = llgoUnreachable
|
ftype = llgoUnreachable
|
||||||
default:
|
default:
|
||||||
@@ -367,7 +371,7 @@ func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, do
|
|||||||
b.SetBlockEx(ret, llssa.AfterInit)
|
b.SetBlockEx(ret, llssa.AfterInit)
|
||||||
for _, modName := range modNames {
|
for _, modName := range modNames {
|
||||||
objs := mods[modName]
|
objs := mods[modName]
|
||||||
b.LoadPyModSyms(modName, objs...)
|
b.PyLoadModSyms(modName, objs...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -391,13 +395,13 @@ func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, do
|
|||||||
jumpTo := p.jumpTo(jump)
|
jumpTo := p.jumpTo(jump)
|
||||||
modPath := p.pyMod
|
modPath := p.pyMod
|
||||||
modName := pysymPrefix + modPath
|
modName := pysymPrefix + modPath
|
||||||
modPtr := pkg.NewPyModVar(modName, true).Expr
|
modPtr := pkg.PyNewModVar(modName, true).Expr
|
||||||
mod := b.Load(modPtr)
|
mod := b.Load(modPtr)
|
||||||
cond := b.BinOp(token.NEQ, mod, prog.Null(mod.Type))
|
cond := b.BinOp(token.NEQ, mod, prog.Null(mod.Type))
|
||||||
newBlk := p.fn.MakeBlock()
|
newBlk := p.fn.MakeBlock()
|
||||||
b.If(cond, jumpTo, newBlk)
|
b.If(cond, jumpTo, newBlk)
|
||||||
b.SetBlock(newBlk)
|
b.SetBlock(newBlk)
|
||||||
b.Store(modPtr, b.ImportPyMod(modPath))
|
b.Store(modPtr, b.PyImportMod(modPath))
|
||||||
b.Jump(jumpTo)
|
b.Jump(jumpTo)
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
@@ -600,6 +604,9 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
|
|||||||
case pyFunc:
|
case pyFunc:
|
||||||
args := p.compileValues(b, args, kind)
|
args := p.compileValues(b, args, kind)
|
||||||
ret = b.Call(pyFn.Expr, args...)
|
ret = b.Call(pyFn.Expr, args...)
|
||||||
|
case llgoPyList:
|
||||||
|
args := p.compileValues(b, args, fnHasVArg)
|
||||||
|
ret = b.PyList(args...)
|
||||||
case llgoCstr:
|
case llgoCstr:
|
||||||
ret = cstr(b, args)
|
ret = cstr(b, args)
|
||||||
case llgoAdvance:
|
case llgoAdvance:
|
||||||
@@ -797,7 +804,7 @@ func (p *context) compileFunction(v *ssa.Function) (goFn llssa.Function, pyFn ll
|
|||||||
// v.Pkg == nil: means auto generated function?
|
// v.Pkg == nil: means auto generated function?
|
||||||
if v.Pkg == p.goPkg || v.Pkg == nil {
|
if v.Pkg == p.goPkg || v.Pkg == nil {
|
||||||
// function in this package
|
// function in this package
|
||||||
goFn, pyFn, kind = p.compileFuncDecl(p.pkg, v, true)
|
goFn, pyFn, kind = p.compileFuncDecl(p.pkg, v)
|
||||||
if kind != ignoredFunc {
|
if kind != ignoredFunc {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -824,8 +831,7 @@ func (p *context) compileValue(b llssa.Builder, v ssa.Value) llssa.Expr {
|
|||||||
}
|
}
|
||||||
return pyFn.Expr
|
return pyFn.Expr
|
||||||
case *ssa.Global:
|
case *ssa.Global:
|
||||||
g := p.varOf(v)
|
return p.varOf(b, v)
|
||||||
return g.Expr
|
|
||||||
case *ssa.Const:
|
case *ssa.Const:
|
||||||
t := types.Default(v.Type())
|
t := types.Default(v.Type())
|
||||||
return b.Const(v.Value, p.prog.Type(t, llssa.InGo))
|
return b.Const(v.Value, p.prog.Type(t, llssa.InGo))
|
||||||
@@ -916,7 +922,7 @@ func NewPackage(prog llssa.Program, pkg *ssa.Package, files []*ast.File) (ret ll
|
|||||||
// Do not try to build generic (non-instantiated) functions.
|
// Do not try to build generic (non-instantiated) functions.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ctx.compileFuncDecl(ret, member, false)
|
ctx.compileFuncDecl(ret, member)
|
||||||
case *ssa.Type:
|
case *ssa.Type:
|
||||||
ctx.compileType(ret, member)
|
ctx.compileType(ret, member)
|
||||||
case *ssa.Global:
|
case *ssa.Global:
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ func TestFromTestdata(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSqlite(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) {
|
func TestFromTestpymath(t *testing.T) {
|
||||||
|
|||||||
18
cl/import.go
18
cl/import.go
@@ -318,6 +318,7 @@ const (
|
|||||||
llgoAdvance = llgoInstrBase + 4
|
llgoAdvance = llgoInstrBase + 4
|
||||||
llgoIndex = llgoInstrBase + 5
|
llgoIndex = llgoInstrBase + 5
|
||||||
llgoStringData = llgoInstrBase + 6
|
llgoStringData = llgoInstrBase + 6
|
||||||
|
llgoPyList = llgoInstrBase + 7
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p *context) funcName(fn *ssa.Function, ignore bool) (*types.Package, string, int) {
|
func (p *context) funcName(fn *ssa.Function, ignore bool) (*types.Package, string, int) {
|
||||||
@@ -358,24 +359,35 @@ const (
|
|||||||
ignoredVar = iota
|
ignoredVar = iota
|
||||||
goVar = int(llssa.InGo)
|
goVar = int(llssa.InGo)
|
||||||
cVar = int(llssa.InC)
|
cVar = int(llssa.InC)
|
||||||
|
pyVar = int(llssa.InPython)
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p *context) varName(pkg *types.Package, v *ssa.Global) (vName string, vtype int) {
|
func (p *context) varName(pkg *types.Package, v *ssa.Global) (vName string, vtype int) {
|
||||||
name := llssa.FullName(pkg, v.Name())
|
name := llssa.FullName(pkg, v.Name())
|
||||||
if v, ok := p.link[name]; ok {
|
if v, ok := p.link[name]; ok {
|
||||||
|
if strings.HasPrefix(v, "py.") {
|
||||||
|
return v[3:], pyVar
|
||||||
|
}
|
||||||
return v, cVar
|
return v, cVar
|
||||||
}
|
}
|
||||||
return name, goVar
|
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)
|
pkgTypes := p.ensureLoaded(v.Pkg.Pkg)
|
||||||
pkg := p.pkg
|
pkg := p.pkg
|
||||||
name, vtype := p.varName(pkgTypes, v)
|
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))
|
ret = pkg.NewVar(name, v.Type(), llssa.Background(vtype))
|
||||||
}
|
}
|
||||||
return
|
return ret.Expr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) ensureLoaded(pkgTypes *types.Package) *types.Package {
|
func (p *context) ensureLoaded(pkgTypes *types.Package) *types.Package {
|
||||||
|
|||||||
@@ -200,7 +200,9 @@ func buildAllPkgs(prog llssa.Program, initial []*packages.Package, mode Mode, ve
|
|||||||
if isPkgInLLGo(pkgPath) {
|
if isPkgInLLGo(pkgPath) {
|
||||||
pkg.ExportFile = concatPkgLinkFiles(pkgPath)
|
pkg.ExportFile = concatPkgLinkFiles(pkgPath)
|
||||||
} else {
|
} else {
|
||||||
panic("todo")
|
// panic("todo")
|
||||||
|
// TODO(xsw): support packages out of llgo
|
||||||
|
pkg.ExportFile = ""
|
||||||
}
|
}
|
||||||
if kind == cl.PkgLinkExtern { // need to be linked with external library
|
if kind == cl.PkgLinkExtern { // need to be linked with external library
|
||||||
linkFile := os.ExpandEnv(strings.TrimSpace(param))
|
linkFile := os.ExpandEnv(strings.TrimSpace(param))
|
||||||
@@ -209,10 +211,10 @@ func buildAllPkgs(prog llssa.Program, initial []*packages.Package, mode Mode, ve
|
|||||||
if dir != "" {
|
if dir != "" {
|
||||||
command += " -L " + dir
|
command += " -L " + dir
|
||||||
}
|
}
|
||||||
if isMultiLinkFiles(pkg.ExportFile) {
|
if isSingleLinkFile(pkg.ExportFile) {
|
||||||
pkg.ExportFile = command + pkg.ExportFile
|
|
||||||
} else {
|
|
||||||
pkg.ExportFile = command + " " + pkg.ExportFile
|
pkg.ExportFile = command + " " + pkg.ExportFile
|
||||||
|
} else {
|
||||||
|
pkg.ExportFile = command + pkg.ExportFile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -454,14 +456,14 @@ func llgoRoot() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func appendLinkFiles(args []string, file string) []string {
|
func appendLinkFiles(args []string, file string) []string {
|
||||||
if isMultiLinkFiles(file) {
|
if isSingleLinkFile(file) {
|
||||||
return append(args, strings.Split(file[1:], " ")...)
|
|
||||||
}
|
|
||||||
return append(args, file)
|
return append(args, file)
|
||||||
}
|
}
|
||||||
|
return append(args, strings.Split(file[1:], " ")...)
|
||||||
|
}
|
||||||
|
|
||||||
func isMultiLinkFiles(ret string) bool {
|
func isSingleLinkFile(ret string) bool {
|
||||||
return len(ret) > 0 && ret[0] == ' '
|
return len(ret) > 0 && ret[0] != ' '
|
||||||
}
|
}
|
||||||
|
|
||||||
func concatPkgLinkFiles(pkgPath string) string {
|
func concatPkgLinkFiles(pkgPath string) string {
|
||||||
|
|||||||
@@ -103,8 +103,6 @@ func SmartDoFile(inFile string, pkgPath ...string) {
|
|||||||
fname := autgenFile
|
fname := autgenFile
|
||||||
if inCompilerDir(absDir) {
|
if inCompilerDir(absDir) {
|
||||||
fname = "out.ll"
|
fname = "out.ll"
|
||||||
} else if inSqlite(absDir) {
|
|
||||||
fname = "sqlite.ll"
|
|
||||||
}
|
}
|
||||||
outFile := dir + fname
|
outFile := dir + fname
|
||||||
|
|
||||||
@@ -129,7 +127,3 @@ func genZip(dir string, outFile, inFile string) {
|
|||||||
func inCompilerDir(dir string) bool {
|
func inCompilerDir(dir string) bool {
|
||||||
return strings.Contains(dir, "/llgo/cl/")
|
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
40
internal/runtime/slice.go
Normal 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
|
||||||
|
}
|
||||||
@@ -70,4 +70,25 @@ func SliceData(s Slice) unsafe.Pointer {
|
|||||||
return s.data
|
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
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
49
py/_pyg/llpyg/llpyg.c
Normal file
49
py/_pyg/llpyg/llpyg.c
Normal 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;
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
// example:
|
// example:
|
||||||
// llgoLoadPyModSyms(mod, "name1", &func1, "name2", &func2, NULL)
|
// llgoLoadPyModSyms(mod, "name1", &func1, "name2", &func2, NULL)
|
||||||
@@ -23,3 +24,30 @@ void llgoLoadPyModSyms(PyObject* mod, ...) {
|
|||||||
}
|
}
|
||||||
va_end(ap);
|
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
33
py/arg.go
Normal 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
61
py/builtins/builtins.go
Normal 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)
|
||||||
BIN
py/builtins/llgo_autogen.lla
Normal file
BIN
py/builtins/llgo_autogen.lla
Normal file
Binary file not shown.
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package py
|
package py
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "unsafe"
|
_ "unsafe"
|
||||||
|
|
||||||
@@ -44,3 +46,5 @@ func (o *Object) CStr() *c.Char { return nil }
|
|||||||
|
|
||||||
// llgo:link (*Object).Strlen C.PyBytes_Size
|
// llgo:link (*Object).Strlen C.PyBytes_Size
|
||||||
func (o *Object) Strlen() uintptr { return 0 }
|
func (o *Object) Strlen() uintptr { return 0 }
|
||||||
|
|
||||||
|
*/
|
||||||
|
|||||||
131
py/call.go
Normal file
131
py/call.go
Normal 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
41
py/code.go
Normal 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
45
py/dict.go
Normal 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
32
py/exceptions.go
Normal 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()
|
||||||
56
py/func.go
Normal file
56
py/func.go
Normal 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 function’s 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 object’s co_qualname field.
|
||||||
|
//
|
||||||
|
//go:linkname NewFunc C.PyFunction_New
|
||||||
|
func NewFunc(code, globals *Object) *Object
|
||||||
|
|
||||||
|
// As NewFunc, but also allows setting the function object’s __qualname__
|
||||||
|
// attribute. qualname should be a unicode object or nil; if nil, the
|
||||||
|
// __qualname__ attribute is set to the same value as the code object’s
|
||||||
|
// 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
14
py/inspect/doc.txt
Normal 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 function’s 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
617
py/inspect/gen.go
Normal 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
BIN
py/inspect/llgo_autogen.lla
Normal file
Binary file not shown.
152
py/json/gen.go
Normal file
152
py/json/gen.go
Normal 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
BIN
py/json/llgo_autogen.lla
Normal file
Binary file not shown.
96
py/list.go
Normal file
96
py/list.go
Normal 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 }
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"cl": [
|
"cl": [
|
||||||
"clang -emit-llvm -S -o module.ll -c _pyg/module.c",
|
"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",
|
"rm llgo_autogen.lla; zip llgo_autogen.lla llgo_autogen.ll module.ll",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
73
py/long.go
Normal file
73
py/long.go
Normal 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
31
py/math/doc.txt
Normal 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
349
py/math/gen.go
Normal 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
|
||||||
Binary file not shown.
@@ -22,9 +22,30 @@ import (
|
|||||||
"github.com/goplus/llgo/py"
|
"github.com/goplus/llgo/py"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
// https://docs.python.org/3/library/math.html
|
||||||
LLGoPackage = "py.math"
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:linkname Sqrt py.sqrt
|
//go:linkname Pi py.pi
|
||||||
func Sqrt(x *py.Object) *py.Object
|
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
|
||||||
|
|||||||
24
py/module.go
24
py/module.go
@@ -22,7 +22,29 @@ import (
|
|||||||
"github.com/goplus/llgo/c"
|
"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
|
||||||
|
// there’s 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
|
// This is a wrapper around py.Import which takes a const char* as an argument
|
||||||
// instead of an Object.
|
// instead of an Object.
|
||||||
|
|||||||
10195
py/numpy/gen.go
Normal file
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
BIN
py/numpy/llgo_autogen.lla
Normal file
Binary file not shown.
79
py/numpy/numpy.go
Normal file
79
py/numpy/numpy.go
Normal 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
|
||||||
138
py/object.go
138
py/object.go
@@ -22,22 +22,38 @@ import (
|
|||||||
"github.com/goplus/llgo/c"
|
"github.com/goplus/llgo/c"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// https://docs.python.org/3/c-api/object.html
|
||||||
|
|
||||||
// Object represents a Python object.
|
// Object represents a Python object.
|
||||||
type Object struct {
|
type Object struct {
|
||||||
Unused [8]byte
|
Unused [8]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
// llgo:link (*Object).DecRef C.Py_DecRef
|
// llgo:link (*Object).DecRef C.Py_DecRef
|
||||||
func (o *Object) 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,
|
// Retrieve an attribute named attrName from object o. Returns the attribute value on success,
|
||||||
@@ -50,109 +66,3 @@ func (o *Object) GetAttr(attrName *Object) *Object { return nil }
|
|||||||
func (o *Object) GetAttrString(attrName *c.Char) *Object { return nil }
|
func (o *Object) GetAttrString(attrName *c.Char) *Object { return nil }
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
// 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(callable, 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
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|||||||
1429
py/os/gen.go
Normal file
1429
py/os/gen.go
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
22
py/os/os.go
22
py/os/os.go
@@ -22,9 +22,21 @@ import (
|
|||||||
"github.com/goplus/llgo/py"
|
"github.com/goplus/llgo/py"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
// https://docs.python.org/3/library/os.html
|
||||||
LLGoPackage = "py.os"
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:linkname Getcwd py.getcwd
|
// Rename the file or directory src to dst. If dst exists, the operation will
|
||||||
func Getcwd() *py.Object
|
// 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
|
||||||
|
|||||||
401
py/statistics/gen.go
Normal file
401
py/statistics/gen.go
Normal 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
|
||||||
BIN
py/statistics/llgo_autogen.lla
Normal file
BIN
py/statistics/llgo_autogen.lla
Normal file
Binary file not shown.
220
py/sys/gen.go
Normal file
220
py/sys/gen.go
Normal 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
BIN
py/sys/llgo_autogen.lla
Normal file
Binary file not shown.
39
py/tuple.go
Normal file
39
py/tuple.go
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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/tuple.html
|
||||||
|
|
||||||
|
// Return a new tuple object of size len, or nil on failure.
|
||||||
|
//
|
||||||
|
//go:linkname NewTuple C.PyTuple_New
|
||||||
|
func NewTuple(len uintptr) *Object
|
||||||
|
|
||||||
|
// Take a pointer to a tuple object, and return the size of that tuple.
|
||||||
|
//
|
||||||
|
// llgo:link (*Object).TupleLen C.PyTuple_Size
|
||||||
|
func (t *Object) TupleLen() uintptr { return 0 }
|
||||||
|
|
||||||
|
// Return the object at position pos in the tuple pointed to by p. If pos is
|
||||||
|
// negative or out of bounds, return nil and set an IndexError exception.
|
||||||
|
//
|
||||||
|
// llgo:link (*Object).TupleItem C.PyTuple_GetItem
|
||||||
|
func (t *Object) TupleItem(index uintptr) *Object { return nil }
|
||||||
53
py/type.go
Normal file
53
py/type.go
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* 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/type.html
|
||||||
|
|
||||||
|
// Return the type’s name. Equivalent to getting the type’s __name__ attribute.
|
||||||
|
//
|
||||||
|
// llgo:link (*Object).TypeName C.PyType_GetName
|
||||||
|
func (t *Object) TypeName() *Object { return nil }
|
||||||
|
|
||||||
|
// Return the tp_flags member of type. This function is primarily meant for use
|
||||||
|
// with Py_LIMITED_API; the individual flag bits are guaranteed to be stable across
|
||||||
|
// Python releases, but access to tp_flags itself is not part of the limited API.
|
||||||
|
//
|
||||||
|
// llgo:link (*Object).TypeFlags C.PyType_GetFlags
|
||||||
|
func (t *Object) TypeFlags() uint32 { return 0 }
|
||||||
|
|
||||||
|
// Return the module object associated with the given type when the type was created
|
||||||
|
// using PyType_FromModuleAndSpec().
|
||||||
|
//
|
||||||
|
// If no module is associated with the given type, sets TypeError and returns nil.
|
||||||
|
//
|
||||||
|
// This function is usually used to get the module in which a method is defined. Note
|
||||||
|
// that in such a method, Py_TYPE(self).Module() may not return the intended result.
|
||||||
|
// Py_TYPE(self) may be a subclass of the intended class, and subclasses are not
|
||||||
|
// necessarily defined in the same module as their superclass. See PyCMethod to get
|
||||||
|
// the class that defines the method. See ModuleByDef() for cases when PyCMethod
|
||||||
|
// cannot be used.
|
||||||
|
//
|
||||||
|
// llgo:link (*Object).TypeModule C.PyType_GetModule
|
||||||
|
func (t *Object) TypeModule() *Object { return nil }
|
||||||
|
|
||||||
|
// llgo:link (*Object).TypeModuleByDef C.PyType_GetModuleByDef
|
||||||
|
// func (t *Object) TypeModuleByDef(def *ModuleDef) *Object { return nil }
|
||||||
47
py/unicode.go
Normal file
47
py/unicode.go
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* 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/unicode.html
|
||||||
|
|
||||||
|
// Return a pointer to the UTF-8 encoding of the Unicode object, and store the
|
||||||
|
// size of the encoded representation (in bytes) in size. The size argument can
|
||||||
|
// be nil; in this case no size will be stored. The returned buffer always has
|
||||||
|
// an extra null byte appended (not included in size), regardless of whether
|
||||||
|
// there are any other null code points.
|
||||||
|
//
|
||||||
|
// In the case of an error, nil is returned with an exception set and no size is
|
||||||
|
// stored.
|
||||||
|
//
|
||||||
|
// This caches the UTF-8 representation of the string in the Unicode object, and
|
||||||
|
// subsequent calls will return a pointer to the same buffer. The caller is not
|
||||||
|
// responsible for deallocating the buffer. The buffer is deallocated and pointers
|
||||||
|
// to it become invalid when the Unicode object is garbage collected.
|
||||||
|
//
|
||||||
|
// llgo:link (*Object).CStrAndLen C.PyUnicode_AsUTF8AndSize
|
||||||
|
func (u *Object) CStrAndLen() (*c.Char, uintptr) { return nil, 0 }
|
||||||
|
|
||||||
|
// As CStrAndLen, but does not store the len.
|
||||||
|
//
|
||||||
|
// llgo:link (*Object).CStr C.PyUnicode_AsUTF8
|
||||||
|
func (u *Object) CStr() *c.Char { return nil }
|
||||||
44
ssa/decl.go
44
ssa/decl.go
@@ -29,19 +29,16 @@ import (
|
|||||||
const (
|
const (
|
||||||
ClosureCtx = "__llgo_ctx"
|
ClosureCtx = "__llgo_ctx"
|
||||||
ClosureStub = "__llgo_stub."
|
ClosureStub = "__llgo_stub."
|
||||||
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const (
|
||||||
NameValist = "__llgo_va_list"
|
NameValist = "__llgo_va_list"
|
||||||
)
|
)
|
||||||
|
|
||||||
func VArg() *types.Var {
|
func VArg() *types.Var {
|
||||||
return types.NewParam(0, nil, NameValist, types.Typ[types.Invalid])
|
return types.NewParam(0, nil, NameValist, types.NewSlice(tyAny))
|
||||||
}
|
|
||||||
|
|
||||||
func IsVArg(arg *types.Var) bool {
|
|
||||||
return arg.Name() == NameValist
|
|
||||||
}
|
|
||||||
|
|
||||||
func HasVArg(t *types.Tuple, n int) bool {
|
|
||||||
return n > 0 && IsVArg(t.At(n-1))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -196,7 +193,7 @@ func newParams(fn Type, prog Program) (params []Type, hasVArg bool) {
|
|||||||
sig := fn.raw.Type.(*types.Signature)
|
sig := fn.raw.Type.(*types.Signature)
|
||||||
in := sig.Params()
|
in := sig.Params()
|
||||||
if n := in.Len(); n > 0 {
|
if n := in.Len(); n > 0 {
|
||||||
if hasVArg = HasVArg(in, n); hasVArg {
|
if hasVArg = sig.Variadic(); hasVArg {
|
||||||
n--
|
n--
|
||||||
}
|
}
|
||||||
params = make([]Type, n)
|
params = make([]Type, n)
|
||||||
@@ -285,6 +282,29 @@ func (p Function) Block(idx int) BasicBlock {
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type aPyGlobal struct {
|
||||||
|
Expr
|
||||||
|
}
|
||||||
|
|
||||||
|
type PyGlobal = *aPyGlobal
|
||||||
|
|
||||||
|
// PyNewVar creates a Python variable.
|
||||||
|
func (b Builder) PyNewVar(modName, name string) PyGlobal {
|
||||||
|
pkg := b.Func.Pkg
|
||||||
|
modPtr := pkg.PyNewModVar(modName, false).Expr
|
||||||
|
mod := b.Load(modPtr)
|
||||||
|
return &aPyGlobal{pyVarExpr(mod, name)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b Builder) pyLoad(ptr Expr) Expr {
|
||||||
|
pkg := b.Func.Pkg
|
||||||
|
t := ptr.raw.Type.(*pyVarTy)
|
||||||
|
fn := pkg.pyFunc("PyObject_GetAttrString", b.Prog.tyGetAttrString())
|
||||||
|
return b.Call(fn, t.mod, b.CStr(t.name))
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
type aPyObjRef struct {
|
type aPyObjRef struct {
|
||||||
Expr
|
Expr
|
||||||
Obj Global
|
Obj Global
|
||||||
@@ -293,8 +313,8 @@ type aPyObjRef struct {
|
|||||||
// PyObjRef represents a python object reference.
|
// PyObjRef represents a python object reference.
|
||||||
type PyObjRef = *aPyObjRef
|
type PyObjRef = *aPyObjRef
|
||||||
|
|
||||||
// NewPyFunc creates a new python function.
|
// PyNewFunc creates a new python function.
|
||||||
func (p Package) NewPyFunc(name string, sig *types.Signature, doInit bool) PyObjRef {
|
func (p Package) PyNewFunc(name string, sig *types.Signature, doInit bool) PyObjRef {
|
||||||
if v, ok := p.pyobjs[name]; ok {
|
if v, ok := p.pyobjs[name]; ok {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|||||||
109
ssa/expr.go
109
ssa/expr.go
@@ -54,6 +54,26 @@ func (v Expr) Do(b Builder) Expr {
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type pyVarTy struct {
|
||||||
|
mod Expr
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p pyVarTy) Underlying() types.Type {
|
||||||
|
panic("don't call")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p pyVarTy) String() string {
|
||||||
|
return "pyVar"
|
||||||
|
}
|
||||||
|
|
||||||
|
func pyVarExpr(mod Expr, name string) Expr {
|
||||||
|
tvar := &aType{raw: rawType{&pyVarTy{mod, name}}, kind: vkPyVarRef}
|
||||||
|
return Expr{Type: tvar}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
type phisExprTy struct {
|
type phisExprTy struct {
|
||||||
phis []llvm.Value
|
phis []llvm.Value
|
||||||
Type
|
Type
|
||||||
@@ -68,7 +88,8 @@ func (p phisExprTy) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func phisExpr(t Type, phis []llvm.Value) Expr {
|
func phisExpr(t Type, phis []llvm.Value) Expr {
|
||||||
return Expr{Type: &aType{raw: rawType{&phisExprTy{phis, t}}, kind: vkPhisExpr}}
|
tphi := &aType{raw: rawType{&phisExprTy{phis, t}}, kind: vkPhisExpr}
|
||||||
|
return Expr{Type: tphi}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -78,6 +99,11 @@ func (p Program) Null(t Type) Expr {
|
|||||||
return Expr{llvm.ConstNull(t.ll), t}
|
return Expr{llvm.ConstNull(t.ll), t}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PyNull returns a null *PyObject constant expression.
|
||||||
|
func (p Program) PyNull() Expr {
|
||||||
|
return p.Null(p.PyObjectPtr())
|
||||||
|
}
|
||||||
|
|
||||||
// BoolVal returns a boolean constant expression.
|
// BoolVal returns a boolean constant expression.
|
||||||
func (p Program) BoolVal(v bool) Expr {
|
func (p Program) BoolVal(v bool) Expr {
|
||||||
t := p.Bool()
|
t := p.Bool()
|
||||||
@@ -284,7 +310,7 @@ func (b Builder) BinOp(op token.Token, x, y Expr) Expr {
|
|||||||
case vkString:
|
case vkString:
|
||||||
if op == token.ADD {
|
if op == token.ADD {
|
||||||
pkg := b.Func.Pkg
|
pkg := b.Func.Pkg
|
||||||
return b.InlineCall(pkg.rtFunc("StringCat"), x, y)
|
return Expr{b.InlineCall(pkg.rtFunc("StringCat"), x, y).impl, x.Type}
|
||||||
}
|
}
|
||||||
case vkComplex:
|
case vkComplex:
|
||||||
default:
|
default:
|
||||||
@@ -508,6 +534,9 @@ func (b Builder) Load(ptr Expr) Expr {
|
|||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("Load %v\n", ptr.impl)
|
log.Printf("Load %v\n", ptr.impl)
|
||||||
}
|
}
|
||||||
|
if ptr.kind == vkPyVarRef {
|
||||||
|
return b.pyLoad(ptr)
|
||||||
|
}
|
||||||
telem := b.Prog.Elem(ptr.Type)
|
telem := b.Prog.Elem(ptr.Type)
|
||||||
return Expr{llvm.CreateLoad(b.impl, telem.ll, ptr.impl), telem}
|
return Expr{llvm.CreateLoad(b.impl, telem.ll, ptr.impl), telem}
|
||||||
}
|
}
|
||||||
@@ -627,6 +656,36 @@ func (b Builder) StringLen(x Expr) Expr {
|
|||||||
return Expr{ptr, prog.Int()}
|
return Expr{ptr, prog.Int()}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SliceData returns the data pointer of a slice.
|
||||||
|
func (b Builder) SliceData(x Expr) Expr {
|
||||||
|
if debugInstr {
|
||||||
|
log.Printf("SliceData %v\n", x.impl)
|
||||||
|
}
|
||||||
|
prog := b.Prog
|
||||||
|
ptr := llvm.CreateExtractValue(b.impl, x.impl, 0)
|
||||||
|
return Expr{ptr, prog.CStr()}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SliceLen returns the length of a slice.
|
||||||
|
func (b Builder) SliceLen(x Expr) Expr {
|
||||||
|
if debugInstr {
|
||||||
|
log.Printf("SliceLen %v\n", x.impl)
|
||||||
|
}
|
||||||
|
prog := b.Prog
|
||||||
|
ptr := llvm.CreateExtractValue(b.impl, x.impl, 1)
|
||||||
|
return Expr{ptr, prog.Int()}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SliceCap returns the length of a slice cap.
|
||||||
|
func (b Builder) SliceCap(x Expr) Expr {
|
||||||
|
if debugInstr {
|
||||||
|
log.Printf("SliceCap %v\n", x.impl)
|
||||||
|
}
|
||||||
|
prog := b.Prog
|
||||||
|
ptr := llvm.CreateExtractValue(b.impl, x.impl, 2)
|
||||||
|
return Expr{ptr, prog.Int()}
|
||||||
|
}
|
||||||
|
|
||||||
// The IndexAddr instruction yields the address of the element at
|
// The IndexAddr instruction yields the address of the element at
|
||||||
// index `idx` of collection `x`. `idx` is an integer expression.
|
// index `idx` of collection `x`. `idx` is an integer expression.
|
||||||
//
|
//
|
||||||
@@ -648,8 +707,7 @@ func (b Builder) IndexAddr(x, idx Expr) Expr {
|
|||||||
pt := prog.Pointer(telem)
|
pt := prog.Pointer(telem)
|
||||||
switch x.raw.Type.Underlying().(type) {
|
switch x.raw.Type.Underlying().(type) {
|
||||||
case *types.Slice:
|
case *types.Slice:
|
||||||
pkg := b.Func.Pkg
|
ptr := b.SliceData(x)
|
||||||
ptr := b.InlineCall(pkg.rtFunc("SliceData"), x)
|
|
||||||
indices := []llvm.Value{idx.impl}
|
indices := []llvm.Value{idx.impl}
|
||||||
return Expr{llvm.CreateInBoundsGEP(b.impl, telem.ll, ptr.impl, indices), pt}
|
return Expr{llvm.CreateInBoundsGEP(b.impl, telem.ll, ptr.impl, indices), pt}
|
||||||
}
|
}
|
||||||
@@ -752,12 +810,12 @@ func (b Builder) Slice(x, low, high, max Expr) (ret Expr) {
|
|||||||
return
|
return
|
||||||
case *types.Slice:
|
case *types.Slice:
|
||||||
nEltSize = b.SizeOf(prog.Index(x.Type))
|
nEltSize = b.SizeOf(prog.Index(x.Type))
|
||||||
nCap = b.InlineCall(pkg.rtFunc("SliceCap"), x)
|
nCap = b.SliceCap(x)
|
||||||
if high.IsNil() {
|
if high.IsNil() {
|
||||||
high = b.InlineCall(pkg.rtFunc("SliceLen"), x)
|
high = b.SliceCap(x)
|
||||||
}
|
}
|
||||||
ret.Type = x.Type
|
ret.Type = x.Type
|
||||||
base = b.InlineCall(pkg.rtFunc("SliceData"), x)
|
base = b.SliceData(x)
|
||||||
case *types.Pointer:
|
case *types.Pointer:
|
||||||
telem := t.Elem()
|
telem := t.Elem()
|
||||||
switch te := telem.Underlying().(type) {
|
switch te := telem.Underlying().(type) {
|
||||||
@@ -1292,21 +1350,40 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) {
|
|||||||
case "len":
|
case "len":
|
||||||
if len(args) == 1 {
|
if len(args) == 1 {
|
||||||
arg := args[0]
|
arg := args[0]
|
||||||
switch t := arg.raw.Type.Underlying().(type) {
|
switch arg.kind {
|
||||||
case *types.Slice:
|
case vkSlice:
|
||||||
return b.InlineCall(b.Func.Pkg.rtFunc("SliceLen"), arg)
|
return b.SliceLen(arg)
|
||||||
case *types.Basic:
|
case vkString:
|
||||||
if t.Kind() == types.String {
|
|
||||||
return b.StringLen(arg)
|
return b.StringLen(arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
case "cap":
|
case "cap":
|
||||||
if len(args) == 1 {
|
if len(args) == 1 {
|
||||||
arg := args[0]
|
arg := args[0]
|
||||||
switch arg.raw.Type.Underlying().(type) {
|
switch arg.kind {
|
||||||
case *types.Slice:
|
case vkSlice:
|
||||||
return b.InlineCall(b.Func.Pkg.rtFunc("SliceCap"), arg)
|
return b.SliceCap(arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "append":
|
||||||
|
if len(args) == 2 {
|
||||||
|
src := args[0]
|
||||||
|
if src.kind == vkSlice {
|
||||||
|
elem := args[1]
|
||||||
|
switch elem.kind {
|
||||||
|
case vkSlice:
|
||||||
|
etSize := b.Prog.SizeOf(b.Prog.Elem(elem.Type))
|
||||||
|
ret.Type = src.Type
|
||||||
|
ret.impl = b.InlineCall(b.Func.Pkg.rtFunc("SliceAppend"),
|
||||||
|
src, b.SliceData(elem), b.SliceLen(elem), b.Prog.Val(int(etSize))).impl
|
||||||
|
return
|
||||||
|
case vkString:
|
||||||
|
etSize := b.Prog.SizeOf(b.Prog.Type(types.Typ[types.Byte], InGo))
|
||||||
|
ret.Type = src.Type
|
||||||
|
ret.impl = b.InlineCall(b.Func.Pkg.rtFunc("SliceAppend"),
|
||||||
|
src, b.StringData(elem), b.StringLen(elem), b.Prog.Val(int(etSize))).impl
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
198
ssa/package.go
198
ssa/package.go
@@ -130,6 +130,7 @@ type aProgram struct {
|
|||||||
voidPtr Type
|
voidPtr Type
|
||||||
boolTy Type
|
boolTy Type
|
||||||
cstrTy Type
|
cstrTy Type
|
||||||
|
cintTy Type
|
||||||
stringTy Type
|
stringTy Type
|
||||||
uintptrTy Type
|
uintptrTy Type
|
||||||
intTy Type
|
intTy Type
|
||||||
@@ -138,9 +139,16 @@ type aProgram struct {
|
|||||||
pyObjPPtr Type
|
pyObjPPtr Type
|
||||||
|
|
||||||
pyImpTy *types.Signature
|
pyImpTy *types.Signature
|
||||||
|
pyNewList *types.Signature
|
||||||
|
pyListSetI *types.Signature
|
||||||
|
callArgs *types.Signature
|
||||||
callNoArgs *types.Signature
|
callNoArgs *types.Signature
|
||||||
callOneArg *types.Signature
|
callOneArg *types.Signature
|
||||||
|
callFOArgs *types.Signature
|
||||||
loadPyModS *types.Signature
|
loadPyModS *types.Signature
|
||||||
|
getAttrStr *types.Signature
|
||||||
|
|
||||||
|
paramObjPtr_ *types.Var
|
||||||
|
|
||||||
NeedRuntime bool
|
NeedRuntime bool
|
||||||
NeedPyInit bool
|
NeedPyInit bool
|
||||||
@@ -328,6 +336,13 @@ func (p Program) Any() Type {
|
|||||||
return p.anyTy
|
return p.anyTy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p Program) CInt() Type {
|
||||||
|
if p.cintTy == nil { // C.int
|
||||||
|
p.cintTy = p.rawType(types.Typ[types.Int32]) // TODO(xsw): support 64-bit
|
||||||
|
}
|
||||||
|
return p.cintTy
|
||||||
|
}
|
||||||
|
|
||||||
// Int returns int type.
|
// Int returns int type.
|
||||||
func (p Program) Int() Type {
|
func (p Program) Int() Type {
|
||||||
if p.intTy == nil {
|
if p.intTy == nil {
|
||||||
@@ -475,31 +490,38 @@ func (p *Package) WriteFile(file string) (err error) {
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func (p Program) paramObjPtr() *types.Var {
|
||||||
|
if p.paramObjPtr_ == nil {
|
||||||
|
objPtr := p.PyObjectPtr().raw.Type
|
||||||
|
p.paramObjPtr_ = types.NewParam(token.NoPos, nil, "", objPtr)
|
||||||
|
}
|
||||||
|
return p.paramObjPtr_
|
||||||
|
}
|
||||||
|
|
||||||
|
// func(*char) *Object
|
||||||
func (p Program) tyImportPyModule() *types.Signature {
|
func (p Program) tyImportPyModule() *types.Signature {
|
||||||
if p.pyImpTy == nil {
|
if p.pyImpTy == nil {
|
||||||
charPtr := types.NewPointer(types.Typ[types.Int8])
|
charPtr := types.NewPointer(types.Typ[types.Int8])
|
||||||
objPtr := p.PyObjectPtr().raw.Type
|
|
||||||
params := types.NewTuple(types.NewParam(token.NoPos, nil, "", charPtr))
|
params := types.NewTuple(types.NewParam(token.NoPos, nil, "", charPtr))
|
||||||
results := types.NewTuple(types.NewParam(token.NoPos, nil, "", objPtr))
|
results := types.NewTuple(p.paramObjPtr())
|
||||||
p.pyImpTy = types.NewSignatureType(nil, nil, nil, params, results, false)
|
p.pyImpTy = types.NewSignatureType(nil, nil, nil, params, results, false)
|
||||||
}
|
}
|
||||||
return p.pyImpTy
|
return p.pyImpTy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func(*Object) *Object
|
||||||
func (p Program) tyCallNoArgs() *types.Signature {
|
func (p Program) tyCallNoArgs() *types.Signature {
|
||||||
if p.callNoArgs == nil {
|
if p.callNoArgs == nil {
|
||||||
objPtr := p.PyObjectPtr().raw.Type
|
params := types.NewTuple(p.paramObjPtr())
|
||||||
paramObjPtr := types.NewParam(token.NoPos, nil, "", objPtr)
|
|
||||||
params := types.NewTuple(paramObjPtr)
|
|
||||||
p.callNoArgs = types.NewSignatureType(nil, nil, nil, params, params, false)
|
p.callNoArgs = types.NewSignatureType(nil, nil, nil, params, params, false)
|
||||||
}
|
}
|
||||||
return p.callNoArgs
|
return p.callNoArgs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func(*Object, *Object) *Object
|
||||||
func (p Program) tyCallOneArg() *types.Signature {
|
func (p Program) tyCallOneArg() *types.Signature {
|
||||||
if p.callOneArg == nil {
|
if p.callOneArg == nil {
|
||||||
objPtr := p.PyObjectPtr().raw.Type
|
paramObjPtr := p.paramObjPtr()
|
||||||
paramObjPtr := types.NewParam(token.NoPos, nil, "", objPtr)
|
|
||||||
params := types.NewTuple(paramObjPtr, paramObjPtr)
|
params := types.NewTuple(paramObjPtr, paramObjPtr)
|
||||||
results := types.NewTuple(paramObjPtr)
|
results := types.NewTuple(paramObjPtr)
|
||||||
p.callOneArg = types.NewSignatureType(nil, nil, nil, params, results, false)
|
p.callOneArg = types.NewSignatureType(nil, nil, nil, params, results, false)
|
||||||
@@ -507,29 +529,101 @@ func (p Program) tyCallOneArg() *types.Signature {
|
|||||||
return p.callOneArg
|
return p.callOneArg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func(*Object, ...) *Object
|
||||||
|
func (p Program) tyCallFunctionObjArgs() *types.Signature {
|
||||||
|
if p.callFOArgs == nil {
|
||||||
|
paramObjPtr := p.paramObjPtr()
|
||||||
|
params := types.NewTuple(paramObjPtr, VArg())
|
||||||
|
results := types.NewTuple(paramObjPtr)
|
||||||
|
p.callFOArgs = types.NewSignatureType(nil, nil, nil, params, results, true)
|
||||||
|
}
|
||||||
|
return p.callFOArgs
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// func(*Object, *Object, *Object) *Object
|
||||||
|
func (p Program) tyCall() *types.Signature {
|
||||||
|
if p.callArgs == nil {
|
||||||
|
paramObjPtr := p.paramObjPtr()
|
||||||
|
params := types.NewTuple(paramObjPtr, paramObjPtr, paramObjPtr)
|
||||||
|
results := types.NewTuple(paramObjPtr)
|
||||||
|
p.callArgs = types.NewSignatureType(nil, nil, nil, params, results, false)
|
||||||
|
}
|
||||||
|
return p.callArgs
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// func(*Object, uintptr, *Object) cint
|
||||||
|
func (p Program) tyListSetItem() *types.Signature {
|
||||||
|
if p.pyListSetI == nil {
|
||||||
|
paramUintptr := types.NewParam(token.NoPos, nil, "", p.Uintptr().raw.Type)
|
||||||
|
paramCInt := types.NewParam(token.NoPos, nil, "", p.CInt().raw.Type)
|
||||||
|
paramObjPtr := p.paramObjPtr()
|
||||||
|
params := types.NewTuple(paramObjPtr, paramUintptr, paramObjPtr)
|
||||||
|
results := types.NewTuple(paramCInt)
|
||||||
|
p.pyListSetI = types.NewSignatureType(nil, nil, nil, params, results, false)
|
||||||
|
}
|
||||||
|
return p.pyListSetI
|
||||||
|
}
|
||||||
|
|
||||||
|
// func(uintptr) *Object
|
||||||
|
func (p Program) tyNewList() *types.Signature {
|
||||||
|
if p.pyNewList == nil {
|
||||||
|
paramUintptr := types.NewParam(token.NoPos, nil, "", p.Uintptr().raw.Type)
|
||||||
|
params := types.NewTuple(paramUintptr)
|
||||||
|
results := types.NewTuple(p.paramObjPtr())
|
||||||
|
p.pyNewList = types.NewSignatureType(nil, nil, nil, params, results, false)
|
||||||
|
}
|
||||||
|
return p.pyNewList
|
||||||
|
}
|
||||||
|
|
||||||
|
// func(float64) *Object
|
||||||
|
func (p Program) tyFloatFromDouble() *types.Signature {
|
||||||
|
if p.callArgs == nil {
|
||||||
|
paramObjPtr := p.paramObjPtr()
|
||||||
|
paramFloat := types.NewParam(token.NoPos, nil, "", p.Float64().raw.Type)
|
||||||
|
params := types.NewTuple(paramFloat)
|
||||||
|
results := types.NewTuple(paramObjPtr)
|
||||||
|
p.callArgs = types.NewSignatureType(nil, nil, nil, params, results, false)
|
||||||
|
}
|
||||||
|
return p.callArgs
|
||||||
|
}
|
||||||
|
|
||||||
|
// func(*Object, ...)
|
||||||
func (p Program) tyLoadPyModSyms() *types.Signature {
|
func (p Program) tyLoadPyModSyms() *types.Signature {
|
||||||
if p.loadPyModS == nil {
|
if p.loadPyModS == nil {
|
||||||
objPtr := p.PyObjectPtr().raw.Type
|
paramObjPtr := p.paramObjPtr()
|
||||||
paramObjPtr := types.NewParam(token.NoPos, nil, "mod", objPtr)
|
|
||||||
params := types.NewTuple(paramObjPtr, VArg())
|
params := types.NewTuple(paramObjPtr, VArg())
|
||||||
p.loadPyModS = types.NewSignatureType(nil, nil, nil, params, nil, false)
|
p.loadPyModS = types.NewSignatureType(nil, nil, nil, params, nil, true)
|
||||||
}
|
}
|
||||||
return p.loadPyModS
|
return p.loadPyModS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func(*Objecg, *char) *Object
|
||||||
|
func (p Program) tyGetAttrString() *types.Signature {
|
||||||
|
if p.getAttrStr == nil {
|
||||||
|
charPtr := types.NewPointer(types.Typ[types.Int8])
|
||||||
|
paramObjPtr := p.paramObjPtr()
|
||||||
|
params := types.NewTuple(paramObjPtr, types.NewParam(token.NoPos, nil, "", charPtr))
|
||||||
|
results := types.NewTuple(paramObjPtr)
|
||||||
|
p.getAttrStr = types.NewSignatureType(nil, nil, nil, params, results, false)
|
||||||
|
}
|
||||||
|
return p.getAttrStr
|
||||||
|
}
|
||||||
|
|
||||||
// PyInit initializes Python for a main package.
|
// PyInit initializes Python for a main package.
|
||||||
func (p Package) PyInit() bool {
|
func (p Package) PyInit() bool {
|
||||||
if fn := p.FuncOf("main"); fn != nil {
|
if fn := p.FuncOf("main"); fn != nil {
|
||||||
b := fn.NewBuilder()
|
b := fn.NewBuilder()
|
||||||
b.SetBlockEx(fn.Block(0), AtStart).CallPyInit()
|
b.SetBlockEx(fn.Block(0), AtStart).callPyInit()
|
||||||
b.Dispose()
|
b.Dispose()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPyModVar creates a new global variable for a Python module.
|
// PyNewModVar creates a new global variable for a Python module.
|
||||||
func (p Package) NewPyModVar(name string, doInit bool) Global {
|
func (p Package) PyNewModVar(name string, doInit bool) Global {
|
||||||
if v, ok := p.pymods[name]; ok {
|
if v, ok := p.pymods[name]; ok {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
@@ -544,18 +638,18 @@ func (p Package) NewPyModVar(name string, doInit bool) Global {
|
|||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImportPyMod imports a Python module.
|
// PyImportMod imports a Python module.
|
||||||
func (b Builder) ImportPyMod(path string) Expr {
|
func (b Builder) PyImportMod(path string) Expr {
|
||||||
pkg := b.Func.Pkg
|
pkg := b.Func.Pkg
|
||||||
fnImp := pkg.pyFunc("PyImport_ImportModule", b.Prog.tyImportPyModule())
|
fnImp := pkg.pyFunc("PyImport_ImportModule", b.Prog.tyImportPyModule())
|
||||||
return b.Call(fnImp, b.CStr(path))
|
return b.Call(fnImp, b.CStr(path))
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadPyModSyms loads python objects from specified module.
|
// PyLoadModSyms loads python objects from specified module.
|
||||||
func (b Builder) LoadPyModSyms(modName string, objs ...PyObjRef) Expr {
|
func (b Builder) PyLoadModSyms(modName string, objs ...PyObjRef) Expr {
|
||||||
pkg := b.Func.Pkg
|
pkg := b.Func.Pkg
|
||||||
fnLoad := pkg.pyFunc("llgoLoadPyModSyms", b.Prog.tyLoadPyModSyms())
|
fnLoad := pkg.pyFunc("llgoLoadPyModSyms", b.Prog.tyLoadPyModSyms())
|
||||||
modPtr := pkg.NewPyModVar(modName, false).Expr
|
modPtr := pkg.PyNewModVar(modName, false).Expr
|
||||||
mod := b.Load(modPtr)
|
mod := b.Load(modPtr)
|
||||||
args := make([]Expr, 1, len(objs)*2+2)
|
args := make([]Expr, 1, len(objs)*2+2)
|
||||||
args[0] = mod
|
args[0] = mod
|
||||||
@@ -583,16 +677,76 @@ func (b Builder) pyCall(fn Expr, args []Expr) (ret Expr) {
|
|||||||
call := pkg.pyFunc("PyObject_CallNoArgs", prog.tyCallNoArgs())
|
call := pkg.pyFunc("PyObject_CallNoArgs", prog.tyCallNoArgs())
|
||||||
ret = b.Call(call, fn)
|
ret = b.Call(call, fn)
|
||||||
case 1:
|
case 1:
|
||||||
|
if !sig.Variadic() {
|
||||||
call := pkg.pyFunc("PyObject_CallOneArg", prog.tyCallOneArg())
|
call := pkg.pyFunc("PyObject_CallOneArg", prog.tyCallOneArg())
|
||||||
ret = b.Call(call, fn, args[0])
|
return b.Call(call, fn, args[0])
|
||||||
|
}
|
||||||
|
fallthrough
|
||||||
default:
|
default:
|
||||||
panic("todo")
|
call := pkg.pyFunc("PyObject_CallFunctionObjArgs", prog.tyCallFunctionObjArgs())
|
||||||
|
n = len(args)
|
||||||
|
callargs := make([]Expr, n+2)
|
||||||
|
callargs[0] = fn
|
||||||
|
copy(callargs[1:], args)
|
||||||
|
callargs[n+1] = prog.PyNull()
|
||||||
|
ret = b.Call(call, callargs...)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// CallPyInit calls Py_Initialize.
|
// PyNewList(n uintptr) *Object
|
||||||
func (b Builder) CallPyInit() (ret Expr) {
|
func (b Builder) PyNewList(n Expr) (ret Expr) {
|
||||||
|
prog := b.Prog
|
||||||
|
pkg := b.Func.Pkg
|
||||||
|
fn := pkg.pyFunc("PyList_New", prog.tyNewList())
|
||||||
|
return b.Call(fn, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PyListSetItem(list *Object, index uintptr, item *Object) c.Int
|
||||||
|
func (b Builder) PyListSetItem(list, index, item Expr) (ret Expr) {
|
||||||
|
prog := b.Prog
|
||||||
|
pkg := b.Func.Pkg
|
||||||
|
fn := pkg.pyFunc("PyList_SetItem", prog.tyListSetItem())
|
||||||
|
return b.Call(fn, list, index, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PyList(args ...Expr) *Object
|
||||||
|
func (b Builder) PyList(args ...Expr) (ret Expr) {
|
||||||
|
prog := b.Prog
|
||||||
|
n := len(args)
|
||||||
|
uintPtr := prog.Uintptr()
|
||||||
|
list := b.PyNewList(prog.IntVal(uint64(n), uintPtr))
|
||||||
|
for i, arg := range args {
|
||||||
|
b.PyListSetItem(list, prog.IntVal(uint64(i), uintPtr), b.PyVal(arg))
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
// PyVal(v any) *Object
|
||||||
|
func (b Builder) PyVal(v Expr) (ret Expr) {
|
||||||
|
switch t := v.raw.Type.(type) {
|
||||||
|
case *types.Basic:
|
||||||
|
switch t.Kind() {
|
||||||
|
case types.Float64:
|
||||||
|
return b.PyFloat(v)
|
||||||
|
default:
|
||||||
|
panic("PyVal: todo")
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PyFloat(fltVal float64) *Object
|
||||||
|
func (b Builder) PyFloat(fltVal Expr) (ret Expr) {
|
||||||
|
prog := b.Prog
|
||||||
|
pkg := b.Func.Pkg
|
||||||
|
fn := pkg.pyFunc("PyFloat_FromDouble", prog.tyFloatFromDouble())
|
||||||
|
return b.Call(fn, fltVal)
|
||||||
|
}
|
||||||
|
|
||||||
|
// callPyInit calls Py_Initialize.
|
||||||
|
func (b Builder) callPyInit() (ret Expr) {
|
||||||
fn := b.Func.Pkg.pyFunc("Py_Initialize", NoArgsNoRet)
|
fn := b.Func.Pkg.pyFunc("Py_Initialize", NoArgsNoRet)
|
||||||
return b.Call(fn)
|
return b.Call(fn)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,7 +102,9 @@ func TestCvtType(t *testing.T) {
|
|||||||
|
|
||||||
func TestUserdefExpr(t *testing.T) {
|
func TestUserdefExpr(t *testing.T) {
|
||||||
b := &phisExprTy{}
|
b := &phisExprTy{}
|
||||||
|
c := &pyVarTy{}
|
||||||
_ = b.String()
|
_ = b.String()
|
||||||
|
_ = c.String()
|
||||||
test := func(a types.Type) {
|
test := func(a types.Type) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r == nil {
|
if r := recover(); r == nil {
|
||||||
@@ -112,6 +114,7 @@ func TestUserdefExpr(t *testing.T) {
|
|||||||
a.Underlying()
|
a.Underlying()
|
||||||
}
|
}
|
||||||
test(b)
|
test(b)
|
||||||
|
test(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAny(t *testing.T) {
|
func TestAny(t *testing.T) {
|
||||||
@@ -143,12 +146,12 @@ func TestPyFunc(t *testing.T) {
|
|||||||
prog.SetPython(py)
|
prog.SetPython(py)
|
||||||
pkg := prog.NewPackage("bar", "foo/bar")
|
pkg := prog.NewPackage("bar", "foo/bar")
|
||||||
sig := types.NewSignatureType(nil, nil, nil, nil, nil, false)
|
sig := types.NewSignatureType(nil, nil, nil, nil, nil, false)
|
||||||
a := pkg.NewPyFunc("a", sig, false)
|
a := pkg.PyNewFunc("a", sig, false)
|
||||||
if pkg.NewPyFunc("a", sig, false) != a {
|
if pkg.PyNewFunc("a", sig, false) != a {
|
||||||
t.Fatal("NewPyFunc(a) failed")
|
t.Fatal("NewPyFunc(a) failed")
|
||||||
}
|
}
|
||||||
foo := pkg.NewPyModVar("foo", false)
|
foo := pkg.PyNewModVar("foo", false)
|
||||||
if pkg.NewPyModVar("foo", false) != foo {
|
if pkg.PyNewModVar("foo", false) != foo {
|
||||||
t.Fatal("NewPyModVar(foo) failed")
|
t.Fatal("NewPyModVar(foo) failed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -399,8 +402,8 @@ func TestPrintf(t *testing.T) {
|
|||||||
pchar := types.NewPointer(types.Typ[types.Int8])
|
pchar := types.NewPointer(types.Typ[types.Int8])
|
||||||
params := types.NewTuple(types.NewVar(0, nil, "format", pchar), VArg())
|
params := types.NewTuple(types.NewVar(0, nil, "format", pchar), VArg())
|
||||||
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int32]))
|
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int32]))
|
||||||
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
sig := types.NewSignatureType(nil, nil, nil, params, rets, true)
|
||||||
pkg.NewFunc("printf", sig, InGo)
|
pkg.NewFunc("printf", sig, InC)
|
||||||
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
||||||
source_filename = "foo/bar"
|
source_filename = "foo/bar"
|
||||||
|
|
||||||
|
|||||||
11
ssa/type.go
11
ssa/type.go
@@ -44,7 +44,9 @@ const (
|
|||||||
vkFuncPtr
|
vkFuncPtr
|
||||||
vkClosure
|
vkClosure
|
||||||
vkPyFuncRef
|
vkPyFuncRef
|
||||||
|
vkPyVarRef
|
||||||
vkTuple
|
vkTuple
|
||||||
|
vkSlice
|
||||||
vkPhisExpr = -1
|
vkPhisExpr = -1
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -103,7 +105,10 @@ func (p Program) Pointer(typ Type) Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) Elem(typ Type) Type {
|
func (p Program) Elem(typ Type) Type {
|
||||||
elem := typ.raw.Type.(*types.Pointer).Elem()
|
elem := typ.raw.Type.(interface {
|
||||||
|
types.Type
|
||||||
|
Elem() types.Type
|
||||||
|
}).Elem()
|
||||||
return p.rawType(elem)
|
return p.rawType(elem)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,7 +242,7 @@ func (p Program) toType(raw types.Type) Type {
|
|||||||
case *types.Interface:
|
case *types.Interface:
|
||||||
return &aType{p.rtIface(), typ, vkInvalid}
|
return &aType{p.rtIface(), typ, vkInvalid}
|
||||||
case *types.Slice:
|
case *types.Slice:
|
||||||
return &aType{p.rtSlice(), typ, vkInvalid}
|
return &aType{p.rtSlice(), typ, vkSlice}
|
||||||
case *types.Map:
|
case *types.Map:
|
||||||
return &aType{p.rtMap(), typ, vkInvalid}
|
return &aType{p.rtMap(), typ, vkInvalid}
|
||||||
case *types.Struct:
|
case *types.Struct:
|
||||||
@@ -313,7 +318,7 @@ func (p Program) toLLVMTypes(t *types.Tuple, n int) (ret []llvm.Type) {
|
|||||||
func (p Program) toLLVMFunc(sig *types.Signature) llvm.Type {
|
func (p Program) toLLVMFunc(sig *types.Signature) llvm.Type {
|
||||||
tParams := sig.Params()
|
tParams := sig.Params()
|
||||||
n := tParams.Len()
|
n := tParams.Len()
|
||||||
hasVArg := HasVArg(tParams, n)
|
hasVArg := sig.Variadic()
|
||||||
if hasVArg {
|
if hasVArg {
|
||||||
n--
|
n--
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,6 +66,27 @@ func (p Program) FuncDecl(sig *types.Signature, bg Background) Type {
|
|||||||
return &aType{p.toLLVMFunc(sig), rawType{sig}, vkFuncDecl}
|
return &aType{p.toLLVMFunc(sig), rawType{sig}, vkFuncDecl}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// cvtCxFunc converts a C extended function type into raw type.
|
||||||
|
func cvtCxFunc(sig *types.Signature, recv *types.Var) *types.Signature {
|
||||||
|
if sig.Variadic() {
|
||||||
|
// convert printf-like function type
|
||||||
|
tParams := sig.Params()
|
||||||
|
n := tParams.Len()
|
||||||
|
params := make([]*types.Var, n)
|
||||||
|
n--
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
params[i] = tParams.At(i)
|
||||||
|
}
|
||||||
|
params[n] = VArg()
|
||||||
|
sig = types.NewSignatureType(nil, nil, nil, types.NewTuple(params...), sig.Results(), true)
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
sig = FuncAddCtx(recv, sig)
|
||||||
|
return sig
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// Closure creates a closture type for a function.
|
// Closure creates a closture type for a function.
|
||||||
func (p Program) Closure(fn Type) Type {
|
func (p Program) Closure(fn Type) Type {
|
||||||
sig := fn.raw.Type.(*types.Signature)
|
sig := fn.raw.Type.(*types.Signature)
|
||||||
@@ -151,8 +172,9 @@ func (p goTypes) cvtFunc(sig *types.Signature, recv *types.Var) (raw *types.Sign
|
|||||||
}
|
}
|
||||||
params, cvt1 := p.cvtTuple(sig.Params())
|
params, cvt1 := p.cvtTuple(sig.Params())
|
||||||
results, cvt2 := p.cvtTuple(sig.Results())
|
results, cvt2 := p.cvtTuple(sig.Results())
|
||||||
if cvt1 || cvt2 {
|
if cvt1 || cvt2 || sig.Variadic() {
|
||||||
return types.NewSignatureType(nil, nil, nil, params, results, sig.Variadic())
|
// variadic always is false in raw type for Go function
|
||||||
|
return types.NewSignatureType(nil, nil, nil, params, results, false)
|
||||||
}
|
}
|
||||||
return sig
|
return sig
|
||||||
}
|
}
|
||||||
|
|||||||
35
x/cjson/README.md
Normal file
35
x/cjson/README.md
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
LLGo wrapper of DaveGamble/cJSON
|
||||||
|
=====
|
||||||
|
[](https://github.com/goplus/cjson/actions/workflows/go.yml)
|
||||||
|
[](https://github.com/goplus/cjson/releases)
|
||||||
|
[](https://pkg.go.dev/github.com/goplus/cjson)
|
||||||
|
[](https://github.com/goplus/llgo)
|
||||||
|
[](https://github.com/goplus/gop)
|
||||||
|
|
||||||
|
## How to install
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git clone https://github.com/goplus/cjson.git
|
||||||
|
cd cjson
|
||||||
|
git submodule init
|
||||||
|
git submodule update
|
||||||
|
mkdir build.dir
|
||||||
|
cd build.dir
|
||||||
|
cmake ../cJSON
|
||||||
|
sudo make install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Demos
|
||||||
|
|
||||||
|
The `_demo` directory contains our demos (it start with `_` to prevent the `go` command from compiling it):
|
||||||
|
|
||||||
|
* [mkjson](_demo/mkjson/mkjson.go): create a json object and print it
|
||||||
|
|
||||||
|
### How to run demos
|
||||||
|
|
||||||
|
To run the demos in directory `_demo`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd <demo-directory> # eg. cd _demo/mkjson
|
||||||
|
llgo run .
|
||||||
|
```
|
||||||
27
x/cjson/_demo/mkjson/mkjson.go
Normal file
27
x/cjson/_demo/mkjson/mkjson.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/x/cjson"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
mod := cjson.Object()
|
||||||
|
mod.SetItem(c.Str("name"), cjson.String(c.Str("math")))
|
||||||
|
|
||||||
|
syms := cjson.Array()
|
||||||
|
|
||||||
|
fn := cjson.Object()
|
||||||
|
fn.SetItem(c.Str("name"), cjson.String(c.Str("sqrt")))
|
||||||
|
fn.SetItem(c.Str("sig"), cjson.String(c.Str("(x, /)")))
|
||||||
|
syms.AddItem(fn)
|
||||||
|
|
||||||
|
v := cjson.Object()
|
||||||
|
v.SetItem(c.Str("name"), cjson.String(c.Str("pi")))
|
||||||
|
syms.AddItem(v)
|
||||||
|
|
||||||
|
mod.SetItem(c.Str("items"), syms)
|
||||||
|
|
||||||
|
c.Printf(c.Str("%s\n"), mod.CStr())
|
||||||
|
mod.Delete()
|
||||||
|
}
|
||||||
116
x/cjson/cjson.go
Normal file
116
x/cjson/cjson.go
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* 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 cjson
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LLGoPackage = "link: cjson"
|
||||||
|
)
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type JSON struct {
|
||||||
|
Unused [0]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname Null C.cJSON_CreateNull
|
||||||
|
func Null() *JSON
|
||||||
|
|
||||||
|
//go:linkname True C.cJSON_CreateTrue
|
||||||
|
func True() *JSON
|
||||||
|
|
||||||
|
//go:linkname False C.cJSON_CreateFalse
|
||||||
|
func False() *JSON
|
||||||
|
|
||||||
|
//go:linkname Bool C.cJSON_CreateBool
|
||||||
|
func Bool(boolean c.Int) *JSON
|
||||||
|
|
||||||
|
//go:linkname Number C.cJSON_CreateNumber
|
||||||
|
func Number(num float64) *JSON
|
||||||
|
|
||||||
|
//go:linkname String C.cJSON_CreateString
|
||||||
|
func String(str *c.Char) *JSON
|
||||||
|
|
||||||
|
//go:linkname Array C.cJSON_CreateArray
|
||||||
|
func Array() *JSON
|
||||||
|
|
||||||
|
//go:linkname Object C.cJSON_CreateObject
|
||||||
|
func Object() *JSON
|
||||||
|
|
||||||
|
// raw json
|
||||||
|
//
|
||||||
|
//go:linkname Raw C.cJSON_CreateRaw
|
||||||
|
func Raw(raw *c.Char) *JSON
|
||||||
|
|
||||||
|
// Create a string where valuestring references a string so
|
||||||
|
// it will not be freed by Delete
|
||||||
|
//
|
||||||
|
//go:linkname StringRef C.cJSON_CreateStringReference
|
||||||
|
func StringRef(str *c.Char) *JSON
|
||||||
|
|
||||||
|
// Create an object that only references it's elements so
|
||||||
|
// they will not be freed by Delete
|
||||||
|
//
|
||||||
|
//go:linkname ObjectRef C.cJSON_CreateObjectReference
|
||||||
|
func ObjectRef(child *JSON) *JSON
|
||||||
|
|
||||||
|
// Create an array that only references it's elements so
|
||||||
|
// they will not be freed by Delete
|
||||||
|
//
|
||||||
|
//go:linkname ArrayRef C.cJSON_CreateArrayReference
|
||||||
|
func ArrayRef(child *JSON) *JSON
|
||||||
|
|
||||||
|
// Delete a JSON entity and all subentities.
|
||||||
|
//
|
||||||
|
// llgo:link (*JSON).Delete C.cJSON_Delete
|
||||||
|
func (o *JSON) Delete() {}
|
||||||
|
|
||||||
|
// Append item to the specified array.
|
||||||
|
//
|
||||||
|
// llgo:link (*JSON).AddItem C.cJSON_AddItemToArray
|
||||||
|
func (o *JSON) AddItem(item *JSON) c.Int { return 0 }
|
||||||
|
|
||||||
|
// Append item to the specified object.
|
||||||
|
//
|
||||||
|
// llgo:link (*JSON).SetItem C.cJSON_AddItemToObject
|
||||||
|
func (o *JSON) SetItem(key *c.Char, item *JSON) c.Int { return 0 }
|
||||||
|
|
||||||
|
// llgo:link (*JSON).CStr C.cJSON_PrintUnformatted
|
||||||
|
func (o *JSON) CStr() *c.Char { return nil }
|
||||||
|
|
||||||
|
// Render a JSON entity to text for transfer/storage.
|
||||||
|
//
|
||||||
|
// llgo:link (*JSON).Print C.cJSON_Print
|
||||||
|
func (o *JSON) Print() *c.Char { return nil }
|
||||||
|
|
||||||
|
// Render a JSON entity to text for transfer/storage without any formatting.
|
||||||
|
//
|
||||||
|
// llgo:link (*JSON).PrintUnformatted C.cJSON_PrintUnformatted
|
||||||
|
func (o *JSON) PrintUnformatted() *c.Char { return nil }
|
||||||
|
|
||||||
|
// Render a JSON entity to text using a buffered strategy.
|
||||||
|
//
|
||||||
|
// prebuffer is a guess at the final size. guessing well reduces reallocation.
|
||||||
|
//
|
||||||
|
// fmt=0 gives unformatted, =1 gives formatted.
|
||||||
|
//
|
||||||
|
// llgo:link (*JSON).PrintBuffered C.cJSON_PrintBuffered
|
||||||
|
func (o *JSON) PrintBuffered(prebuffer c.Int, fmt c.Int) *c.Char { return nil }
|
||||||
BIN
x/cjson/llgo_autogen.lla
Normal file
BIN
x/cjson/llgo_autogen.lla
Normal file
Binary file not shown.
35
x/sqlite/README.md
Normal file
35
x/sqlite/README.md
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
LLGo wrapper of sqlite
|
||||||
|
=====
|
||||||
|
[](https://github.com/goplus/sqlite/actions/workflows/go.yml)
|
||||||
|
[](https://github.com/goplus/sqlite/releases)
|
||||||
|
[](https://pkg.go.dev/github.com/goplus/sqlite)
|
||||||
|
[](https://github.com/goplus/llgo)
|
||||||
|
[](https://github.com/goplus/gop)
|
||||||
|
|
||||||
|
## How to install
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git clone https://github.com/goplus/sqlite.git
|
||||||
|
cd sqlite
|
||||||
|
git submodule init
|
||||||
|
git submodule update
|
||||||
|
mkdir build.dir
|
||||||
|
cd build.dir
|
||||||
|
../sqlite/configure --enable-shared
|
||||||
|
sudo make install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Demos
|
||||||
|
|
||||||
|
The `_demo` directory contains our demos (it start with `_` to prevent the `go` command from compiling it):
|
||||||
|
|
||||||
|
* [sqlitedemo](_demo/sqlitedemo/demo.go): a basic sqlite demo
|
||||||
|
|
||||||
|
### How to run demos
|
||||||
|
|
||||||
|
To run the demos in directory `_demo`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd <demo-directory> # eg. cd _demo/sqlitedemo
|
||||||
|
llgo run .
|
||||||
|
```
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"cl": [
|
|
||||||
"mkdir build.dir",
|
|
||||||
"cd build.dir",
|
|
||||||
"../sqlite/configure",
|
|
||||||
"make",
|
|
||||||
"clang -emit-llvm -S -o ../llgo_autogen.ll -c sqlite3.c",
|
|
||||||
"cd ..; rm llgo_autogen.lla; zip llgo_autogen.lla llgo_autogen.ll sqlite.ll",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Binary file not shown.
Submodule x/sqlite/sqlite deleted from b74eb00e2c
@@ -29,15 +29,17 @@ type (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LLGoPackage = "link"
|
LLGoPackage = "link: sqlite3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// llgo:type C
|
// llgo:type C
|
||||||
type Sqlite3 struct {
|
type Sqlite3 struct {
|
||||||
|
Unused [8]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// llgo:type C
|
// llgo:type C
|
||||||
type Stmt struct {
|
type Stmt struct {
|
||||||
|
Unused [8]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -1,99 +0,0 @@
|
|||||||
; ModuleID = 'github.com/goplus/llgo/x/sqlite'
|
|
||||||
source_filename = "github.com/goplus/llgo/x/sqlite"
|
|
||||||
|
|
||||||
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
|
|
||||||
|
|
||||||
@"github.com/goplus/llgo/x/sqlite.init$guard" = global ptr null
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/x/sqlite.Errno).Errstr"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = load i32, ptr %0, align 4
|
|
||||||
%2 = call ptr @sqlite3_errstr(i32 %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define { ptr, i32 } @"github.com/goplus/llgo/x/sqlite.Open"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 8)
|
|
||||||
%2 = call i32 @sqlite3_open(ptr %0, ptr %1)
|
|
||||||
%3 = load ptr, ptr %1, align 8
|
|
||||||
%mrv = insertvalue { ptr, i32 } poison, ptr %3, 0
|
|
||||||
%mrv1 = insertvalue { ptr, i32 } %mrv, i32 %2, 1
|
|
||||||
ret { ptr, i32 } %mrv1
|
|
||||||
}
|
|
||||||
|
|
||||||
define { ptr, i32 } @"github.com/goplus/llgo/x/sqlite.OpenV2"(ptr %0, i32 %1, ptr %2) {
|
|
||||||
_llgo_0:
|
|
||||||
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 8)
|
|
||||||
%4 = call i32 @sqlite3_open_v2(ptr %0, ptr %3, i32 %1, ptr %2)
|
|
||||||
%5 = load ptr, ptr %3, align 8
|
|
||||||
%mrv = insertvalue { ptr, i32 } poison, ptr %5, 0
|
|
||||||
%mrv1 = insertvalue { ptr, i32 } %mrv, i32 %4, 1
|
|
||||||
ret { ptr, i32 } %mrv1
|
|
||||||
}
|
|
||||||
|
|
||||||
define { ptr, i32 } @"(*github.com/goplus/llgo/x/sqlite.Sqlite3).Prepare"(ptr %0, %"github.com/goplus/llgo/internal/runtime.String" %1, ptr %2) {
|
|
||||||
_llgo_0:
|
|
||||||
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 8)
|
|
||||||
%4 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %1, 0
|
|
||||||
%5 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %1, 1
|
|
||||||
%6 = trunc i64 %5 to i32
|
|
||||||
%7 = call i32 @sqlite3_prepare(ptr %0, ptr %4, i32 %6, ptr %3, ptr %2)
|
|
||||||
%8 = load ptr, ptr %3, align 8
|
|
||||||
%mrv = insertvalue { ptr, i32 } poison, ptr %8, 0
|
|
||||||
%mrv1 = insertvalue { ptr, i32 } %mrv, i32 %7, 1
|
|
||||||
ret { ptr, i32 } %mrv1
|
|
||||||
}
|
|
||||||
|
|
||||||
define { ptr, i32 } @"(*github.com/goplus/llgo/x/sqlite.Sqlite3).PrepareV2"(ptr %0, %"github.com/goplus/llgo/internal/runtime.String" %1, ptr %2) {
|
|
||||||
_llgo_0:
|
|
||||||
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 8)
|
|
||||||
%4 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %1, 0
|
|
||||||
%5 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %1, 1
|
|
||||||
%6 = trunc i64 %5 to i32
|
|
||||||
%7 = call i32 @sqlite3_prepare_v2(ptr %0, ptr %4, i32 %6, ptr %3, ptr %2)
|
|
||||||
%8 = load ptr, ptr %3, align 8
|
|
||||||
%mrv = insertvalue { ptr, i32 } poison, ptr %8, 0
|
|
||||||
%mrv1 = insertvalue { ptr, i32 } %mrv, i32 %7, 1
|
|
||||||
ret { ptr, i32 } %mrv1
|
|
||||||
}
|
|
||||||
|
|
||||||
define { ptr, i32 } @"(*github.com/goplus/llgo/x/sqlite.Sqlite3).PrepareV3"(ptr %0, %"github.com/goplus/llgo/internal/runtime.String" %1, i32 %2, ptr %3) {
|
|
||||||
_llgo_0:
|
|
||||||
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 8)
|
|
||||||
%5 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %1, 0
|
|
||||||
%6 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %1, 1
|
|
||||||
%7 = trunc i64 %6 to i32
|
|
||||||
%8 = call i32 @sqlite3_prepare_v3(ptr %0, ptr %5, i32 %7, i32 %2, ptr %4, ptr %3)
|
|
||||||
%9 = load ptr, ptr %4, align 8
|
|
||||||
%mrv = insertvalue { ptr, i32 } poison, ptr %9, 0
|
|
||||||
%mrv1 = insertvalue { ptr, i32 } %mrv, i32 %8, 1
|
|
||||||
ret { ptr, i32 } %mrv1
|
|
||||||
}
|
|
||||||
|
|
||||||
define void @"github.com/goplus/llgo/x/sqlite.init"() {
|
|
||||||
_llgo_0:
|
|
||||||
%0 = load i1, ptr @"github.com/goplus/llgo/x/sqlite.init$guard", align 1
|
|
||||||
br i1 %0, label %_llgo_2, label %_llgo_1
|
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_0
|
|
||||||
store i1 true, ptr @"github.com/goplus/llgo/x/sqlite.init$guard", align 1
|
|
||||||
br label %_llgo_2
|
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
declare ptr @sqlite3_errstr(i32)
|
|
||||||
|
|
||||||
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
|
|
||||||
|
|
||||||
declare i32 @sqlite3_open(ptr, ptr)
|
|
||||||
|
|
||||||
declare i32 @sqlite3_open_v2(ptr, ptr, i32, ptr)
|
|
||||||
|
|
||||||
declare i32 @sqlite3_prepare(ptr, ptr, i32, ptr, ptr)
|
|
||||||
|
|
||||||
declare i32 @sqlite3_prepare_v2(ptr, ptr, i32, ptr, ptr)
|
|
||||||
|
|
||||||
declare i32 @sqlite3_prepare_v3(ptr, ptr, i32, i32, ptr, ptr)
|
|
||||||
Reference in New Issue
Block a user