Compare commits
129 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
621f05c687 | ||
|
|
daf97eabab | ||
|
|
ee3d11cb53 | ||
|
|
1bc7e5e0a5 | ||
|
|
9280d23b1a | ||
|
|
cacd52f81d | ||
|
|
95f64761ca | ||
|
|
6e24792b9b | ||
|
|
9afe26f1d6 | ||
|
|
e7d959da90 | ||
|
|
c3f0867d2c | ||
|
|
1eaf124d4e | ||
|
|
03076bdc76 | ||
|
|
cd32d6debe | ||
|
|
3212f059ff | ||
|
|
9ae4b93083 | ||
|
|
aae7af2194 | ||
|
|
63f4c73ef0 | ||
|
|
f93d3381e0 | ||
|
|
099c80e04b | ||
|
|
14face336e | ||
|
|
67b10d8d38 | ||
|
|
1219230168 | ||
|
|
8d840e694d | ||
|
|
87382aad4d | ||
|
|
aca3a05222 | ||
|
|
84ca145663 | ||
|
|
01d0338851 | ||
|
|
f427c0532d | ||
|
|
c8532a548c | ||
|
|
1e3aef5b94 | ||
|
|
0d3180271b | ||
|
|
f0d17b13f2 | ||
|
|
9a46301d46 | ||
|
|
3bd609ee41 | ||
|
|
2c7f0e8583 | ||
|
|
ce36a25ba3 | ||
|
|
c53484f92e | ||
|
|
f391ccb8e8 | ||
|
|
a96d6a8148 | ||
|
|
bdca09007d | ||
|
|
c0e84043c9 | ||
|
|
0a884df74f | ||
|
|
519b14d506 | ||
|
|
f008a65d91 | ||
|
|
61bb70cd30 | ||
|
|
68fa3dadb0 | ||
|
|
eb38d03976 | ||
|
|
d480bb3ecd | ||
|
|
dfdb6fa1a6 | ||
|
|
42352d9f57 | ||
|
|
eae1c5db70 | ||
|
|
cc37097164 | ||
|
|
6597cc9ce8 | ||
|
|
b3f752d46c | ||
|
|
679e2d0f6b | ||
|
|
4607079ca9 | ||
|
|
ad1a42d6a5 | ||
|
|
afdf31a66c | ||
|
|
37956e2f05 | ||
|
|
dc6aa66f9a | ||
|
|
f16f16c15e | ||
|
|
3b95cbd960 | ||
|
|
3b5e8edd37 | ||
|
|
5f4571e895 | ||
|
|
2d5e991eaf | ||
|
|
7ba8bb4405 | ||
|
|
82aa181540 | ||
|
|
1a3e17bae8 | ||
|
|
e0e3664fdb | ||
|
|
23bfaf1ba2 | ||
|
|
e7d72b6f53 | ||
|
|
eab26deab9 | ||
|
|
49540dbe5e | ||
|
|
cbd891785e | ||
|
|
b1cc732cb2 | ||
|
|
b3b4f55c68 | ||
|
|
8b6b039c13 | ||
|
|
9dca62ff8b | ||
|
|
e0892fcebb | ||
|
|
adf1443105 | ||
|
|
53c2558d26 | ||
|
|
a5ea240793 | ||
|
|
4cd1629118 | ||
|
|
ce32a73e86 | ||
|
|
8a13fc7cd9 | ||
|
|
708de50887 | ||
|
|
4df478316c | ||
|
|
a5dff9fb15 | ||
|
|
b51f4d53b6 | ||
|
|
7d045842dd | ||
|
|
a9ece9e49d | ||
|
|
e6da067cf8 | ||
|
|
bae40c82b9 | ||
|
|
651edf5bc0 | ||
|
|
3a8642b1e0 | ||
|
|
09b6b9259c | ||
|
|
907f326788 | ||
|
|
4a350d8ad9 | ||
|
|
3881db0b4e | ||
|
|
9edae3e877 | ||
|
|
236208e393 | ||
|
|
4ff98de707 | ||
|
|
54964629fe | ||
|
|
072f606784 | ||
|
|
21d2338ec1 | ||
|
|
0d468e0df4 | ||
|
|
5007d49c83 | ||
|
|
35ba69a175 | ||
|
|
fa0ce2a14c | ||
|
|
389750d7d8 | ||
|
|
6c7db7ad23 | ||
|
|
2986426251 | ||
|
|
56444ebcaf | ||
|
|
c63a1978cb | ||
|
|
9d9e998d49 | ||
|
|
f7c991fa9a | ||
|
|
4d14fbb1e7 | ||
|
|
5428730e7a | ||
|
|
bf773df099 | ||
|
|
6dea5100b1 | ||
|
|
aa55f4dceb | ||
|
|
516e92926a | ||
|
|
2cd9994321 | ||
|
|
e69306a2ba | ||
|
|
93ecd031bd | ||
|
|
4eaf69dfa7 | ||
|
|
bc93bda1b7 | ||
|
|
6923f0df2a |
23
.github/workflows/go.yml
vendored
23
.github/workflows/go.yml
vendored
@@ -14,30 +14,29 @@ jobs:
|
|||||||
test:
|
test:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [macos-latest, ubuntu-latest]
|
os:
|
||||||
# os: [macos-latest]
|
- macos-latest
|
||||||
|
- ubuntu-24.04
|
||||||
llvm: [18]
|
llvm: [18]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Update Homebrew
|
- name: Install dependencies
|
||||||
# needed as long as LLVM 18 is still fresh
|
|
||||||
if: matrix.llvm == 18 && startsWith(matrix.os, 'macos')
|
|
||||||
run: brew update
|
|
||||||
- name: Install LLVM ${{ matrix.llvm }} and bdw-gc
|
|
||||||
if: startsWith(matrix.os, 'macos')
|
if: startsWith(matrix.os, 'macos')
|
||||||
run: |
|
run: |
|
||||||
HOMEBREW_NO_AUTO_UPDATE=1 brew install llvm@${{ matrix.llvm }} bdw-gc
|
brew update
|
||||||
echo `brew --prefix llvm@${{ matrix.llvm }}`/bin >> $GITHUB_PATH
|
brew install llvm@${{ matrix.llvm }} pkg-config bdw-gc openssl cjson sqlite python@3.12
|
||||||
- name: Install LLVM ${{ matrix.llvm }} and libgc-dev
|
echo "$(brew --prefix llvm@${{ matrix.llvm }})/bin" >> $GITHUB_PATH
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
if: startsWith(matrix.os, 'ubuntu')
|
if: startsWith(matrix.os, 'ubuntu')
|
||||||
run: |
|
run: |
|
||||||
echo "deb http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-${{ matrix.llvm }} main" | sudo tee /etc/apt/sources.list.d/llvm.list
|
echo "deb http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-${{ matrix.llvm }} main" | sudo tee /etc/apt/sources.list.d/llvm.list
|
||||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y llvm-${{ matrix.llvm }}-dev clang-${{ matrix.llvm }} lld-${{ matrix.llvm }} pkg-config libgc-dev libcjson-dev libsqlite3-dev python3.11-dev
|
sudo apt-get install -y llvm-${{ matrix.llvm }}-dev clang-${{ matrix.llvm }} lld-${{ matrix.llvm }} pkg-config libgc-dev libssl-dev libcjson-dev libsqlite3-dev python3.12-dev
|
||||||
echo /usr/lib/llvm-${{ matrix.llvm }}/bin >> $GITHUB_PATH
|
echo "/usr/lib/llvm-${{ matrix.llvm }}/bin" >> $GITHUB_PATH
|
||||||
|
|
||||||
- name: Clang information
|
- name: Clang information
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
31
README.md
31
README.md
@@ -218,6 +218,7 @@ The currently supported libraries include:
|
|||||||
* [c/llama2](https://pkg.go.dev/github.com/goplus/llgo/c/llama2)
|
* [c/llama2](https://pkg.go.dev/github.com/goplus/llgo/c/llama2)
|
||||||
* [c/lua](https://pkg.go.dev/github.com/goplus/llgo/c/lua)
|
* [c/lua](https://pkg.go.dev/github.com/goplus/llgo/c/lua)
|
||||||
* [c/neco](https://pkg.go.dev/github.com/goplus/llgo/c/neco)
|
* [c/neco](https://pkg.go.dev/github.com/goplus/llgo/c/neco)
|
||||||
|
* [c/openssl](https://pkg.go.dev/github.com/goplus/llgo/c/openssl)
|
||||||
* [c/raylib](https://pkg.go.dev/github.com/goplus/llgo/c/raylib)
|
* [c/raylib](https://pkg.go.dev/github.com/goplus/llgo/c/raylib)
|
||||||
* [c/sqlite](https://pkg.go.dev/github.com/goplus/llgo/c/sqlite)
|
* [c/sqlite](https://pkg.go.dev/github.com/goplus/llgo/c/sqlite)
|
||||||
* [c/zlib](https://pkg.go.dev/github.com/goplus/llgo/c/zlib)
|
* [c/zlib](https://pkg.go.dev/github.com/goplus/llgo/c/zlib)
|
||||||
@@ -243,7 +244,7 @@ All Go syntax (not including `cgo`) is already supported. Here are some examples
|
|||||||
* [goroutine](_demo/goroutine/goroutine.go): goroutine demo
|
* [goroutine](_demo/goroutine/goroutine.go): goroutine demo
|
||||||
|
|
||||||
|
|
||||||
## Defer
|
### Defer
|
||||||
|
|
||||||
LLGo `defer` does not support usage in loops. This is not a bug but a feature, because we think that using `defer` in a loop is a very unrecommended practice.
|
LLGo `defer` does not support usage in loops. This is not a bug but a feature, because we think that using `defer` in a loop is a very unrecommended practice.
|
||||||
|
|
||||||
@@ -270,6 +271,7 @@ Here are the Go packages that can be imported correctly:
|
|||||||
* [math](https://pkg.go.dev/math)
|
* [math](https://pkg.go.dev/math)
|
||||||
* [math/bits](https://pkg.go.dev/math/bits)
|
* [math/bits](https://pkg.go.dev/math/bits)
|
||||||
* [math/cmplx](https://pkg.go.dev/math/cmplx)
|
* [math/cmplx](https://pkg.go.dev/math/cmplx)
|
||||||
|
* [math/rand](https://pkg.go.dev/math/rand)
|
||||||
* [errors](https://pkg.go.dev/errors)
|
* [errors](https://pkg.go.dev/errors)
|
||||||
* [context](https://pkg.go.dev/context)
|
* [context](https://pkg.go.dev/context)
|
||||||
* [io](https://pkg.go.dev/io)
|
* [io](https://pkg.go.dev/io)
|
||||||
@@ -277,8 +279,12 @@ Here are the Go packages that can be imported correctly:
|
|||||||
* [log](https://pkg.go.dev/log)
|
* [log](https://pkg.go.dev/log)
|
||||||
* [flag](https://pkg.go.dev/flag)
|
* [flag](https://pkg.go.dev/flag)
|
||||||
* [sort](https://pkg.go.dev/sort)
|
* [sort](https://pkg.go.dev/sort)
|
||||||
* [strconv](https://pkg.go.dev/strconv)
|
* [bytes](https://pkg.go.dev/bytes)
|
||||||
|
* [bufio](https://pkg.go.dev/bufio)
|
||||||
* [strings](https://pkg.go.dev/strings)
|
* [strings](https://pkg.go.dev/strings)
|
||||||
|
* [strconv](https://pkg.go.dev/strconv)
|
||||||
|
* [path](https://pkg.go.dev/path)
|
||||||
|
* [path/filepath](https://pkg.go.dev/path/filepath)
|
||||||
* [sync/atomic](https://pkg.go.dev/sync/atomic)
|
* [sync/atomic](https://pkg.go.dev/sync/atomic)
|
||||||
* [sync](https://pkg.go.dev/sync) (partially)
|
* [sync](https://pkg.go.dev/sync) (partially)
|
||||||
* [syscall](https://pkg.go.dev/syscall) (partially)
|
* [syscall](https://pkg.go.dev/syscall) (partially)
|
||||||
@@ -288,19 +294,32 @@ Here are the Go packages that can be imported correctly:
|
|||||||
* [fmt](https://pkg.go.dev/fmt) (partially)
|
* [fmt](https://pkg.go.dev/fmt) (partially)
|
||||||
* [reflect](https://pkg.go.dev/reflect) (partially)
|
* [reflect](https://pkg.go.dev/reflect) (partially)
|
||||||
* [time](https://pkg.go.dev/time) (partially)
|
* [time](https://pkg.go.dev/time) (partially)
|
||||||
|
* [encoding/binary](https://pkg.go.dev/encoding/binary)
|
||||||
|
* [encoding/hex](https://pkg.go.dev/encoding/hex)
|
||||||
|
* [encoding/base32](https://pkg.go.dev/encoding/base32)
|
||||||
|
* [encoding/base64](https://pkg.go.dev/encoding/base64)
|
||||||
|
* [encoding/csv](https://pkg.go.dev/encoding/csv)
|
||||||
|
* [hash](https://pkg.go.dev/hash)
|
||||||
|
* [hash/adler32](https://pkg.go.dev/hash/adler32)
|
||||||
|
* [hash/crc32](https://pkg.go.dev/hash/crc32) (partially)
|
||||||
|
* [hash/crc64](https://pkg.go.dev/hash/crc64)
|
||||||
|
* [crypto/md5](https://pkg.go.dev/crypto/md5)
|
||||||
|
* [regexp](https://pkg.go.dev/regexp)
|
||||||
|
* [regexp/syntax](https://pkg.go.dev/regexp/syntax)
|
||||||
|
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
- [Go 1.20+](https://go.dev) (build only)
|
- [Go 1.20+](https://go.dev)
|
||||||
- [LLVM 18](https://llvm.org)
|
- [LLVM 18](https://llvm.org)
|
||||||
- [LLD 18](https://lld.llvm.org)
|
- [LLD 18](https://lld.llvm.org)
|
||||||
- [Clang 18](https://clang.llvm.org)
|
- [Clang 18](https://clang.llvm.org)
|
||||||
- [pkg-config 0.29+](https://www.freedesktop.org/wiki/Software/pkg-config/)
|
- [pkg-config 0.29+](https://www.freedesktop.org/wiki/Software/pkg-config/)
|
||||||
- [bdwgc/libgc 8.0+](https://www.hboehm.info/gc/)
|
- [bdwgc/libgc 8.0+](https://www.hboehm.info/gc/)
|
||||||
|
- [OpenSSL 3.0+](https://www.openssl.org/)
|
||||||
- [cJSON 1.7+](https://github.com/DaveGamble/cJSON) (optional, for [github.com/goplus/llgo/c/cjson](https://pkg.go.dev/github.com/goplus/llgo/c/cjson))
|
- [cJSON 1.7+](https://github.com/DaveGamble/cJSON) (optional, for [github.com/goplus/llgo/c/cjson](https://pkg.go.dev/github.com/goplus/llgo/c/cjson))
|
||||||
- [SQLite 3](https://www.sqlite.org) (optional, for [github.com/goplus/llgo/c/sqlite](https://pkg.go.dev/github.com/goplus/llgo/c/sqlite))
|
- [SQLite 3](https://www.sqlite.org) (optional, for [github.com/goplus/llgo/c/sqlite](https://pkg.go.dev/github.com/goplus/llgo/c/sqlite))
|
||||||
- [Python 3.11+](https://www.python.org) (optional, for [github.com/goplus/llgo/py](https://pkg.go.dev/github.com/goplus/llgo/py))
|
- [Python 3.12+](https://www.python.org) (optional, for [github.com/goplus/llgo/py](https://pkg.go.dev/github.com/goplus/llgo/py))
|
||||||
|
|
||||||
## How to install
|
## How to install
|
||||||
|
|
||||||
@@ -310,7 +329,7 @@ Follow these steps to generate the `llgo` command (its usage is the same as the
|
|||||||
|
|
||||||
```sh
|
```sh
|
||||||
brew update # execute if needed
|
brew update # execute if needed
|
||||||
brew install llvm@18 pkg-config libgc
|
brew install llvm@18 pkg-config bdw-gc openssl
|
||||||
brew install cjson sqlite python@3.12 # optional
|
brew install cjson sqlite python@3.12 # optional
|
||||||
export PATH=$(brew --prefix llvm@18)/bin:$PATH # you may want to add this to your shell RC file, e.g. ~/.zshrc
|
export PATH=$(brew --prefix llvm@18)/bin:$PATH # you may want to add this to your shell RC file, e.g. ~/.zshrc
|
||||||
go install -v github.com/goplus/llgo/cmd/llgo@latest
|
go install -v github.com/goplus/llgo/cmd/llgo@latest
|
||||||
@@ -322,7 +341,7 @@ go install -v github.com/goplus/llgo/cmd/llgo@latest
|
|||||||
echo "deb http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-18 main" | sudo tee /etc/apt/sources.list.d/llvm.list
|
echo "deb http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-18 main" | sudo tee /etc/apt/sources.list.d/llvm.list
|
||||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||||
sudo apt-get update # execute if needed
|
sudo apt-get update # execute if needed
|
||||||
sudo apt-get install -y llvm-18-dev clang-18 lld-18 pkg-config libgc-dev
|
sudo apt-get install -y llvm-18-dev clang-18 lld-18 pkg-config libgc-dev libssl-dev
|
||||||
sudo apt-get install -y libcjson-dev libsqlite3-dev python3.12-dev # optional
|
sudo apt-get install -y libcjson-dev libsqlite3-dev python3.12-dev # optional
|
||||||
export PATH=/usr/lib/llvm-18/bin:$PATH # you may want to add this to your shell RC file, e.g. ~/.bashrc
|
export PATH=/usr/lib/llvm-18/bin:$PATH # you may want to add this to your shell RC file, e.g. ~/.bashrc
|
||||||
go install -v github.com/goplus/llgo/cmd/llgo@latest
|
go install -v github.com/goplus/llgo/cmd/llgo@latest
|
||||||
|
|||||||
47
_cmptest/_bigsqrt2/sqrt2.go
Normal file
47
_cmptest/_bigsqrt2/sqrt2.go
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// We'll do computations with 200 bits of precision in the mantissa.
|
||||||
|
const prec = 200
|
||||||
|
|
||||||
|
// Compute the square root of 2 using Newton's Method. We start with
|
||||||
|
// an initial estimate for sqrt(2), and then iterate:
|
||||||
|
// x_{n+1} = 1/2 * ( x_n + (2.0 / x_n) )
|
||||||
|
|
||||||
|
// Since Newton's Method doubles the number of correct digits at each
|
||||||
|
// iteration, we need at least log_2(prec) steps.
|
||||||
|
steps := int(math.Log2(prec))
|
||||||
|
|
||||||
|
// Initialize values we need for the computation.
|
||||||
|
two := new(big.Float).SetPrec(prec).SetInt64(2)
|
||||||
|
half := new(big.Float).SetPrec(prec).SetFloat64(0.5)
|
||||||
|
|
||||||
|
// Use 1 as the initial estimate.
|
||||||
|
x := new(big.Float).SetPrec(prec).SetInt64(1)
|
||||||
|
|
||||||
|
// We use t as a temporary variable. There's no need to set its precision
|
||||||
|
// since big.Float values with unset (== 0) precision automatically assume
|
||||||
|
// the largest precision of the arguments when used as the result (receiver)
|
||||||
|
// of a big.Float operation.
|
||||||
|
t := new(big.Float)
|
||||||
|
|
||||||
|
// Iterate.
|
||||||
|
for i := 0; i <= steps; i++ {
|
||||||
|
t.Quo(two, x) // t = 2.0 / x_n
|
||||||
|
t.Add(x, t) // t = x_n + (2.0 / x_n)
|
||||||
|
x.Mul(half, t) // x_{n+1} = 0.5 * t
|
||||||
|
}
|
||||||
|
|
||||||
|
// We can use the usual fmt.Printf verbs since big.Float implements fmt.Formatter
|
||||||
|
fmt.Printf("sqrt(2) = %.50f\n", x)
|
||||||
|
|
||||||
|
// Print the error between 2 and x*x.
|
||||||
|
t.Mul(x, x) // t = x*x
|
||||||
|
fmt.Printf("error = %e\n", t.Sub(two, t))
|
||||||
|
}
|
||||||
16
_cmptest/_jsondemo/json.go
Normal file
16
_cmptest/_jsondemo/json.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := `{"name":"math","items":[{"name":"sqrt","sig":"(x, /)"},{"name":"pi"}]}`
|
||||||
|
data := unsafe.Slice(unsafe.StringData(s), len(s))
|
||||||
|
var v any
|
||||||
|
json.Unmarshal(data, &v)
|
||||||
|
b, _ := json.MarshalIndent(v, "", " ")
|
||||||
|
fmt.Println(string(b))
|
||||||
|
}
|
||||||
@@ -13,7 +13,7 @@ func main() {
|
|||||||
select {
|
select {
|
||||||
case m := <-c:
|
case m := <-c:
|
||||||
handle(m)
|
handle(m)
|
||||||
case <-time.After(10 * time.Second):
|
case <-time.After(time.Second / 10):
|
||||||
fmt.Println("timed out")
|
fmt.Println("timed out")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
48
_cmptest/base64demo/base64.go
Normal file
48
_cmptest/base64demo/base64.go
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base32"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func base64Demo() {
|
||||||
|
msg := "Hello, 世界"
|
||||||
|
encoded := base64.StdEncoding.EncodeToString([]byte(msg))
|
||||||
|
fmt.Println(encoded)
|
||||||
|
decoded, err := base64.StdEncoding.DecodeString(encoded)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("decode error:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println(string(decoded))
|
||||||
|
}
|
||||||
|
|
||||||
|
func base32Demo() {
|
||||||
|
str := "JBSWY3DPFQQHO33SNRSCC==="
|
||||||
|
dst := make([]byte, base32.StdEncoding.DecodedLen(len(str)))
|
||||||
|
n, err := base32.StdEncoding.Decode(dst, []byte(str))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("decode error:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dst = dst[:n]
|
||||||
|
fmt.Printf("%q\n", dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
func hexDemo() {
|
||||||
|
const s = "48656c6c6f20476f7068657221"
|
||||||
|
decoded, err := hex.DecodeString(s)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
fmt.Printf("%s\n", decoded)
|
||||||
|
|
||||||
|
}
|
||||||
|
func main() {
|
||||||
|
base64Demo()
|
||||||
|
base32Demo()
|
||||||
|
hexDemo()
|
||||||
|
}
|
||||||
28
_cmptest/crcdemo/crc.go
Normal file
28
_cmptest/crcdemo/crc.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"hash/adler32"
|
||||||
|
"hash/crc32"
|
||||||
|
"hash/crc64"
|
||||||
|
)
|
||||||
|
|
||||||
|
func crc64Demo() {
|
||||||
|
crc := crc64.MakeTable(crc64.ECMA)
|
||||||
|
fmt.Printf("%016x\n", crc64.Checksum([]byte("Hello world"), crc))
|
||||||
|
}
|
||||||
|
|
||||||
|
func crc32Demo() {
|
||||||
|
crc32q := crc32.MakeTable(crc32.IEEE)
|
||||||
|
fmt.Printf("%08x\n", crc32.Checksum([]byte("Hello world"), crc32q))
|
||||||
|
}
|
||||||
|
|
||||||
|
func adler32Demo() {
|
||||||
|
fmt.Printf("%08x\n", adler32.Checksum([]byte("Hello world")))
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
adler32Demo()
|
||||||
|
crc32Demo()
|
||||||
|
crc64Demo()
|
||||||
|
}
|
||||||
30
_cmptest/csvdemo/csv.go
Normal file
30
_cmptest/csvdemo/csv.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/csv"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
in := `first_name,last_name,username
|
||||||
|
"Rob","Pike",rob
|
||||||
|
Ken,Thompson,ken
|
||||||
|
"Robert","Griesemer","gri"
|
||||||
|
`
|
||||||
|
r := csv.NewReader(strings.NewReader(in))
|
||||||
|
|
||||||
|
for {
|
||||||
|
record, err := r.Read()
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(record)
|
||||||
|
}
|
||||||
|
}
|
||||||
20
_cmptest/envexpand/expand.go
Normal file
20
_cmptest/envexpand/expand.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
mapper := func(placeholderName string) string {
|
||||||
|
switch placeholderName {
|
||||||
|
case "DAY_PART":
|
||||||
|
return "morning"
|
||||||
|
case "NAME":
|
||||||
|
return "Gopher"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(os.Expand("Good ${DAY_PART}, $NAME!", mapper))
|
||||||
|
}
|
||||||
14
_cmptest/md5demo/md5.go
Normal file
14
_cmptest/md5demo/md5.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/md5"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
h := md5.New()
|
||||||
|
io.WriteString(h, "The fog is getting thicker!")
|
||||||
|
io.WriteString(h, "And Leon's getting laaarger!")
|
||||||
|
fmt.Printf("%x", h.Sum(nil))
|
||||||
|
}
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/xtool/env/llvm"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -15,4 +18,7 @@ func main() {
|
|||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
cmd.Run()
|
cmd.Run()
|
||||||
|
|
||||||
|
dir := llvm.New("").BinDir()
|
||||||
|
fmt.Println(dir)
|
||||||
}
|
}
|
||||||
12
_cmptest/printfdemo/demo.go
Normal file
12
_cmptest/printfdemo/demo.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/xtool/nm"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
sym := nm.Symbol{Name: "abc", Type: nm.Text}
|
||||||
|
fmt.Printf("%016x %c %s\n", sym.Addr, sym.Type, sym.Name)
|
||||||
|
}
|
||||||
25
_cmptest/readfiledemo/readf.go
Normal file
25
_cmptest/readfiledemo/readf.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fileName := "err.log"
|
||||||
|
os.WriteFile(fileName, []byte("123"), 0644)
|
||||||
|
|
||||||
|
_, err := os.Stat(fileName)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
fmt.Fprintf(os.Stderr, "File %s not found\n", fileName)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := os.ReadFile(fileName)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "ReadFile: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("%s\n", data)
|
||||||
|
}
|
||||||
11
_cmptest/regexdemo/regex.go
Normal file
11
_cmptest/regexdemo/regex.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/xtool/env"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println(env.ExpandEnv("$(pkg-config --libs bdw-gc)"))
|
||||||
|
}
|
||||||
18
_demo/cmd5demo/md5.go
Normal file
18
_demo/cmd5demo/md5.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c/openssl"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var md5 openssl.MD5_CTX
|
||||||
|
var h = make([]byte, openssl.MD5_LBLOCK)
|
||||||
|
md5.Init()
|
||||||
|
md5.UpdateString("The fog is getting thicker!")
|
||||||
|
md5.UpdateString("And Leon's getting laaarger!")
|
||||||
|
md5.Final(unsafe.SliceData(h))
|
||||||
|
fmt.Printf("%x", h)
|
||||||
|
}
|
||||||
26
_demo/crand/rand.go
Normal file
26
_demo/crand/rand.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/math/rand"
|
||||||
|
"github.com/goplus/llgo/c/time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func fastrand64() uint64 {
|
||||||
|
v1 := uint64(rand.Random())
|
||||||
|
v2 := uint64(rand.Random())
|
||||||
|
return v1 ^ (v2 << 32)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
rand.Srand(c.Uint(time.Time(nil)))
|
||||||
|
fmt.Printf("%x\n", rand.Rand())
|
||||||
|
fmt.Printf("%x\n", rand.Rand())
|
||||||
|
|
||||||
|
rand.Srandom(c.Uint(time.Time(nil)))
|
||||||
|
fmt.Printf("%x\n", rand.Random())
|
||||||
|
fmt.Printf("%x\n", rand.Random())
|
||||||
|
fmt.Printf("%x\n", fastrand64())
|
||||||
|
}
|
||||||
68
_demo/cshademo/sha.go
Normal file
68
_demo/cshademo/sha.go
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c/openssl"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
str := "His money is twice tainted:"
|
||||||
|
|
||||||
|
var sha1 openssl.SHA_CTX
|
||||||
|
sha1.Init()
|
||||||
|
sha1.UpdateString(str)
|
||||||
|
|
||||||
|
h1 := make([]byte, openssl.SHA_DIGEST_LENGTH)
|
||||||
|
sha1.Final(unsafe.SliceData(h1))
|
||||||
|
fmt.Printf("%x\n", h1)
|
||||||
|
|
||||||
|
h2 := make([]byte, openssl.SHA_DIGEST_LENGTH)
|
||||||
|
openssl.SHA1String(str, unsafe.SliceData(h2))
|
||||||
|
fmt.Printf("%x\n", h2)
|
||||||
|
|
||||||
|
var sha256 openssl.SHA256_CTX
|
||||||
|
sha256.Init()
|
||||||
|
sha256.UpdateString(str)
|
||||||
|
h3 := make([]byte, openssl.SHA256_DIGEST_LENGTH)
|
||||||
|
sha256.Final(unsafe.SliceData(h3))
|
||||||
|
fmt.Printf("%x\n", h3)
|
||||||
|
|
||||||
|
h4 := make([]byte, openssl.SHA256_DIGEST_LENGTH)
|
||||||
|
openssl.SHA256String(str, unsafe.SliceData(h4))
|
||||||
|
fmt.Printf("%x\n", h4)
|
||||||
|
|
||||||
|
var sha512 openssl.SHA512_CTX
|
||||||
|
sha512.Init()
|
||||||
|
sha512.UpdateString("His money is twice tainted:")
|
||||||
|
|
||||||
|
h5 := make([]byte, openssl.SHA512_DIGEST_LENGTH)
|
||||||
|
sha512.Final(unsafe.SliceData(h5))
|
||||||
|
fmt.Printf("%x\n", h5)
|
||||||
|
|
||||||
|
h6 := make([]byte, openssl.SHA512_DIGEST_LENGTH)
|
||||||
|
openssl.SHA512String(str, unsafe.SliceData(h6))
|
||||||
|
fmt.Printf("%x\n", h6)
|
||||||
|
|
||||||
|
var sha224 openssl.SHA224_CTX
|
||||||
|
sha224.Init()
|
||||||
|
sha224.UpdateString(str)
|
||||||
|
|
||||||
|
h7 := make([]byte, openssl.SHA224_DIGEST_LENGTH)
|
||||||
|
sha224.Final(unsafe.SliceData(h7))
|
||||||
|
fmt.Printf("%x\n", h7)
|
||||||
|
h8 := make([]byte, openssl.SHA224_DIGEST_LENGTH)
|
||||||
|
openssl.SHA224String(str, unsafe.SliceData(h8))
|
||||||
|
fmt.Printf("%x\n", h8)
|
||||||
|
|
||||||
|
var sha384 openssl.SHA384_CTX
|
||||||
|
sha384.Init()
|
||||||
|
sha384.UpdateString(str)
|
||||||
|
h9 := make([]byte, openssl.SHA384_DIGEST_LENGTH)
|
||||||
|
sha384.Final(unsafe.SliceData(h9))
|
||||||
|
fmt.Printf("%x\n", h9)
|
||||||
|
h10 := make([]byte, openssl.SHA384_DIGEST_LENGTH)
|
||||||
|
openssl.SHA384String(str, unsafe.SliceData(h10))
|
||||||
|
fmt.Printf("%x\n", h10)
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"github.com/goplus/llgo/c"
|
"github.com/goplus/llgo/c"
|
||||||
"github.com/goplus/llgo/c/llama2"
|
"github.com/goplus/llgo/c/llama2"
|
||||||
|
"github.com/goplus/llgo/c/time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -11,7 +12,7 @@ func main() {
|
|||||||
var tokenizerPath *c.Char = c.Str("tokenizer.bin")
|
var tokenizerPath *c.Char = c.Str("tokenizer.bin")
|
||||||
var temperature, topp c.Float = 1.0, 0.9
|
var temperature, topp c.Float = 1.0, 0.9
|
||||||
var steps c.Int = 256
|
var steps c.Int = 256
|
||||||
var rngSeed uint64 = uint64(c.Time(nil))
|
var rngSeed uint64 = uint64(time.Time(nil))
|
||||||
|
|
||||||
loop: // parse command line arguments
|
loop: // parse command line arguments
|
||||||
for {
|
for {
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/goplus/llgo/c"
|
|
||||||
"github.com/goplus/llgo/c/math/rand"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
var s c.Uint = 6
|
|
||||||
rand.Srand(s)
|
|
||||||
rr := rand.RandR(&s)
|
|
||||||
r := rand.Rand()
|
|
||||||
println("r:", r)
|
|
||||||
println("rr:", rr)
|
|
||||||
}
|
|
||||||
12
_demo/randdemo/rand.go
Normal file
12
_demo/randdemo/rand.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println(rand.Intn(100))
|
||||||
|
fmt.Println(rand.Intn(100))
|
||||||
|
fmt.Println(rand.Intn(100))
|
||||||
|
}
|
||||||
3
c/c.go
3
c/c.go
@@ -227,9 +227,6 @@ func Perror(s *Char)
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
//go:linkname Time C.time
|
|
||||||
func Time(*int32) int32
|
|
||||||
|
|
||||||
//go:linkname Usleep C.usleep
|
//go:linkname Usleep C.usleep
|
||||||
func Usleep(useconds Uint) Int
|
func Usleep(useconds Uint) Int
|
||||||
|
|
||||||
|
|||||||
@@ -134,6 +134,18 @@ func (o *JSON) PrintUnformatted() *c.Char { return nil }
|
|||||||
// llgo:link (*JSON).PrintBuffered C.cJSON_PrintBuffered
|
// llgo:link (*JSON).PrintBuffered C.cJSON_PrintBuffered
|
||||||
func (o *JSON) PrintBuffered(prebuffer c.Int, fmt c.Int) *c.Char { return nil }
|
func (o *JSON) PrintBuffered(prebuffer c.Int, fmt c.Int) *c.Char { return nil }
|
||||||
|
|
||||||
|
// llgo:link (*JSON).GetObjectItemCaseSensitive C.cJSON_GetObjectItemCaseSensitive
|
||||||
|
func (o *JSON) GetObjectItemCaseSensitive(key *c.Char) *JSON { return nil }
|
||||||
|
|
||||||
|
// llgo:link (*JSON).GetArraySize C.cJSON_GetArraySize
|
||||||
|
func (o *JSON) GetArraySize() c.Int { return 0 }
|
||||||
|
|
||||||
|
// llgo:link (*JSON).GetArrayItem C.cJSON_GetArrayItem
|
||||||
|
func (o *JSON) GetArrayItem(index c.Int) *JSON { return nil }
|
||||||
|
|
||||||
|
// llgo:link (*JSON).GetStringValue C.cJSON_GetStringValue
|
||||||
|
func (o *JSON) GetStringValue() *c.Char { return nil }
|
||||||
|
|
||||||
//go:linkname Free C.cJSON_free
|
//go:linkname Free C.cJSON_free
|
||||||
func Free(ptr unsafe.Pointer)
|
func Free(ptr unsafe.Pointer)
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ func onOpen(req *libuv.Fs) {
|
|||||||
// Init buffer
|
// Init buffer
|
||||||
iov = libuv.InitBuf((*c.Char)(unsafe.Pointer(&buffer[0])), c.Uint(unsafe.Sizeof(buffer)))
|
iov = libuv.InitBuf((*c.Char)(unsafe.Pointer(&buffer[0])), c.Uint(unsafe.Sizeof(buffer)))
|
||||||
// Read the file
|
// Read the file
|
||||||
readRes := libuv.FsRead(loop, &readReq, libuv.UvFile(libuv.FsGetResult(req)), &iov, 1, -1, onRead)
|
readRes := libuv.FsRead(loop, &readReq, libuv.File(libuv.FsGetResult(req)), &iov, 1, -1, onRead)
|
||||||
if readRes != 0 {
|
if readRes != 0 {
|
||||||
c.Printf(c.Str("Error in FsRead: %s (code: %d)\n"), libuv.Strerror(libuv.Errno(readRes)), readRes)
|
c.Printf(c.Str("Error in FsRead: %s (code: %d)\n"), libuv.Strerror(libuv.Errno(readRes)), readRes)
|
||||||
libuv.LoopClose(loop)
|
libuv.LoopClose(loop)
|
||||||
@@ -63,7 +63,7 @@ func onRead(req *libuv.Fs) {
|
|||||||
} else if libuv.FsGetResult(req) == 0 {
|
} else if libuv.FsGetResult(req) == 0 {
|
||||||
c.Printf(c.Str("EOF\n"))
|
c.Printf(c.Str("EOF\n"))
|
||||||
// Close the file
|
// Close the file
|
||||||
closeRes := libuv.FsClose(loop, &closeReq, libuv.UvFile(libuv.FsGetResult(&openReq)), onClose)
|
closeRes := libuv.FsClose(loop, &closeReq, libuv.File(libuv.FsGetResult(&openReq)), onClose)
|
||||||
if closeRes != 0 {
|
if closeRes != 0 {
|
||||||
// Print the content
|
// Print the content
|
||||||
c.Printf(c.Str("Error in FsClose: %s (code: %d)\n"), libuv.Strerror(libuv.Errno(closeRes)), closeRes)
|
c.Printf(c.Str("Error in FsClose: %s (code: %d)\n"), libuv.Strerror(libuv.Errno(closeRes)), closeRes)
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ type FsType c.Int
|
|||||||
|
|
||||||
type DirentType c.Int
|
type DirentType c.Int
|
||||||
|
|
||||||
type UvFile c.Int
|
type File c.Int
|
||||||
|
|
||||||
// ----------------------------------------------
|
// ----------------------------------------------
|
||||||
|
|
||||||
@@ -85,11 +85,6 @@ type Dirent struct {
|
|||||||
Type DirentType
|
Type DirentType
|
||||||
}
|
}
|
||||||
|
|
||||||
type File struct {
|
|
||||||
Loop *Loop
|
|
||||||
Req *Fs
|
|
||||||
}
|
|
||||||
|
|
||||||
type Stat struct {
|
type Stat struct {
|
||||||
Unused [0]byte
|
Unused [0]byte
|
||||||
}
|
}
|
||||||
@@ -112,7 +107,7 @@ type FsPollCb func(handle *FsPoll, status c.Int, events c.Int)
|
|||||||
/* Fs related function and method */
|
/* Fs related function and method */
|
||||||
|
|
||||||
//go:linkname FsGetType C.uv_fs_get_type
|
//go:linkname FsGetType C.uv_fs_get_type
|
||||||
func FsGetType(req *Fs) *FsType
|
func FsGetType(req *Fs) FsType
|
||||||
|
|
||||||
//go:linkname FsGetPath C.uv_fs_get_path
|
//go:linkname FsGetPath C.uv_fs_get_path
|
||||||
func FsGetPath(req *Fs) *c.Char
|
func FsGetPath(req *Fs) *c.Char
|
||||||
@@ -139,13 +134,13 @@ func DefaultLoop() *Loop
|
|||||||
func FsOpen(loop *Loop, req *Fs, path *c.Char, flags c.Int, mode c.Int, cb FsCb) c.Int
|
func FsOpen(loop *Loop, req *Fs, path *c.Char, flags c.Int, mode c.Int, cb FsCb) c.Int
|
||||||
|
|
||||||
//go:linkname FsClose C.uv_fs_close
|
//go:linkname FsClose C.uv_fs_close
|
||||||
func FsClose(loop *Loop, req *Fs, file UvFile, cb FsCb) c.Int
|
func FsClose(loop *Loop, req *Fs, file File, cb FsCb) c.Int
|
||||||
|
|
||||||
//go:linkname FsRead C.uv_fs_read
|
//go:linkname FsRead C.uv_fs_read
|
||||||
func FsRead(loop *Loop, req *Fs, file UvFile, bufs *Buf, nbufs c.Uint, offset c.LongLong, cb FsCb) c.Int
|
func FsRead(loop *Loop, req *Fs, file File, bufs *Buf, nbufs c.Uint, offset c.LongLong, cb FsCb) c.Int
|
||||||
|
|
||||||
//go:linkname FsWrite C.uv_fs_write
|
//go:linkname FsWrite C.uv_fs_write
|
||||||
func FsWrite(loop *Loop, req *Fs, file UvFile, bufs *Buf, nbufs c.Uint, offset c.LongLong, cb FsCb) c.Int
|
func FsWrite(loop *Loop, req *Fs, file File, bufs *Buf, nbufs c.Uint, offset c.LongLong, cb FsCb) c.Int
|
||||||
|
|
||||||
//go:linkname FsUnlink C.uv_fs_unlink
|
//go:linkname FsUnlink C.uv_fs_unlink
|
||||||
func FsUnlink(loop *Loop, req *Fs, path *c.Char, cb FsCb) c.Int
|
func FsUnlink(loop *Loop, req *Fs, path *c.Char, cb FsCb) c.Int
|
||||||
@@ -166,19 +161,19 @@ func FsRmdir(loop *Loop, req *Fs, path *c.Char, cb FsCb) c.Int
|
|||||||
func FsStat(loop *Loop, req *Fs, path *c.Char, cb FsCb) c.Int
|
func FsStat(loop *Loop, req *Fs, path *c.Char, cb FsCb) c.Int
|
||||||
|
|
||||||
//go:linkname FsFstat C.uv_fs_fstat
|
//go:linkname FsFstat C.uv_fs_fstat
|
||||||
func FsFstat(loop *Loop, req *Fs, file UvFile, cb FsCb) c.Int
|
func FsFstat(loop *Loop, req *Fs, file File, cb FsCb) c.Int
|
||||||
|
|
||||||
//go:linkname FsRename C.uv_fs_rename
|
//go:linkname FsRename C.uv_fs_rename
|
||||||
func FsRename(loop *Loop, req *Fs, path *c.Char, newPath *c.Char, cb FsCb) c.Int
|
func FsRename(loop *Loop, req *Fs, path *c.Char, newPath *c.Char, cb FsCb) c.Int
|
||||||
|
|
||||||
//go:linkname FsFsync C.uv_fs_fsync
|
//go:linkname FsFsync C.uv_fs_fsync
|
||||||
func FsFsync(loop *Loop, req *Fs, file UvFile, cb FsCb) c.Int
|
func FsFsync(loop *Loop, req *Fs, file File, cb FsCb) c.Int
|
||||||
|
|
||||||
//go:linkname FsFdatasync C.uv_fs_fdatasync
|
//go:linkname FsFdatasync C.uv_fs_fdatasync
|
||||||
func FsFdatasync(loop *Loop, req *Fs, file UvFile, cb FsCb) c.Int
|
func FsFdatasync(loop *Loop, req *Fs, file File, cb FsCb) c.Int
|
||||||
|
|
||||||
//go:linkname FsFtruncate C.uv_fs_ftruncate
|
//go:linkname FsFtruncate C.uv_fs_ftruncate
|
||||||
func FsFtruncate(loop *Loop, req *Fs, file UvFile, offset c.LongLong, cb FsCb) c.Int
|
func FsFtruncate(loop *Loop, req *Fs, file File, offset c.LongLong, cb FsCb) c.Int
|
||||||
|
|
||||||
//go:linkname FsSendfile C.uv_fs_sendfile
|
//go:linkname FsSendfile C.uv_fs_sendfile
|
||||||
func FsSendfile(loop *Loop, req *Fs, outFd c.Int, inFd c.Int, inOffset c.LongLong, length c.Int, cb FsCb) c.Int
|
func FsSendfile(loop *Loop, req *Fs, outFd c.Int, inFd c.Int, inOffset c.LongLong, length c.Int, cb FsCb) c.Int
|
||||||
@@ -190,13 +185,13 @@ func FsAccess(loop *Loop, req *Fs, path *c.Char, flags c.Int, cb FsCb) c.Int
|
|||||||
func FsChmod(loop *Loop, req *Fs, path *c.Char, mode c.Int, cb FsCb) c.Int
|
func FsChmod(loop *Loop, req *Fs, path *c.Char, mode c.Int, cb FsCb) c.Int
|
||||||
|
|
||||||
//go:linkname FsFchmod C.uv_fs_fchmod
|
//go:linkname FsFchmod C.uv_fs_fchmod
|
||||||
func FsFchmod(loop *Loop, req *Fs, file UvFile, mode c.Int, cb FsCb) c.Int
|
func FsFchmod(loop *Loop, req *Fs, file File, mode c.Int, cb FsCb) c.Int
|
||||||
|
|
||||||
//go:linkname FsUtime C.uv_fs_utime
|
//go:linkname FsUtime C.uv_fs_utime
|
||||||
func FsUtime(loop *Loop, req *Fs, path *c.Char, atime c.Int, mtime c.Int, cb FsCb) c.Int
|
func FsUtime(loop *Loop, req *Fs, path *c.Char, atime c.Int, mtime c.Int, cb FsCb) c.Int
|
||||||
|
|
||||||
//go:linkname FsFutime C.uv_fs_futime
|
//go:linkname FsFutime C.uv_fs_futime
|
||||||
func FsFutime(loop *Loop, req *Fs, file UvFile, atime c.Int, mtime c.Int, cb FsCb) c.Int
|
func FsFutime(loop *Loop, req *Fs, file File, atime c.Int, mtime c.Int, cb FsCb) c.Int
|
||||||
|
|
||||||
//go:linkname FsLutime C.uv_fs_lutime
|
//go:linkname FsLutime C.uv_fs_lutime
|
||||||
func FsLutime(loop *Loop, req *Fs, path *c.Char, atime c.Int, mtime c.Int, cb FsCb) c.Int
|
func FsLutime(loop *Loop, req *Fs, path *c.Char, atime c.Int, mtime c.Int, cb FsCb) c.Int
|
||||||
@@ -238,7 +233,7 @@ func FsStatfs(loop *Loop, req *Fs, path *c.Char, cb FsCb) c.Int
|
|||||||
func FsChown(loop *Loop, req *Fs, path *c.Char, uid c.Int, gid c.Int, cb FsCb) c.Int
|
func FsChown(loop *Loop, req *Fs, path *c.Char, uid c.Int, gid c.Int, cb FsCb) c.Int
|
||||||
|
|
||||||
//go:linkname FsFchown C.uv_fs_fchown
|
//go:linkname FsFchown C.uv_fs_fchown
|
||||||
func FsFchown(loop *Loop, req *Fs, file UvFile, uid c.Int, gid c.Int, cb FsCb) c.Int
|
func FsFchown(loop *Loop, req *Fs, file File, uid c.Int, gid c.Int, cb FsCb) c.Int
|
||||||
|
|
||||||
//go:linkname FsLchown C.uv_fs_lchown
|
//go:linkname FsLchown C.uv_fs_lchown
|
||||||
func FsLchown(loop *Loop, req *Fs, path *c.Char, uid c.Int, gid c.Int, cb FsCb) c.Int
|
func FsLchown(loop *Loop, req *Fs, path *c.Char, uid c.Int, gid c.Int, cb FsCb) c.Int
|
||||||
|
|||||||
@@ -101,46 +101,14 @@ type Handle struct {
|
|||||||
Unused [96]byte
|
Unused [96]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type Dir struct {
|
|
||||||
Unused [0]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type Stream struct {
|
type Stream struct {
|
||||||
Unused [264]byte
|
Unused [264]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type Pipe struct {
|
|
||||||
Unused [0]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type Tty struct {
|
|
||||||
Unused [0]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type Poll struct {
|
type Poll struct {
|
||||||
Unused [0]byte
|
Unused [0]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type Prepare struct {
|
|
||||||
Unused [0]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type Check struct {
|
|
||||||
Unused [0]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type Idle struct {
|
|
||||||
Unused [0]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type Async struct {
|
|
||||||
Unused [0]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type Process struct {
|
|
||||||
Unused [0]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Request types. */
|
/* Request types. */
|
||||||
|
|
||||||
type Req struct {
|
type Req struct {
|
||||||
@@ -296,8 +264,8 @@ func (handle *Handle) Fileno(fd *OsFd) c.Int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname UvPipe C.uv_pipe
|
//go:linkname Pipe C.uv_pipe
|
||||||
func UvPipe(fds [2]UvFile, readFlags c.Int, writeFlags c.Int) c.Int {
|
func Pipe(fds [2]File, readFlags c.Int, writeFlags c.Int) c.Int {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
42
c/lua/_demo/coroutine-cfunc/coroutine.go
Normal file
42
c/lua/_demo/coroutine-cfunc/coroutine.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/lua"
|
||||||
|
)
|
||||||
|
|
||||||
|
func coroutineFunc(L *lua.State) c.Int {
|
||||||
|
c.Printf(c.Str("Coroutine started\n"))
|
||||||
|
L.Yield(0) // Pause the coroutine
|
||||||
|
c.Printf(c.Str("Coroutine resumed\n"))
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
L := lua.Newstate()
|
||||||
|
defer L.Close()
|
||||||
|
|
||||||
|
L.Openlibs()
|
||||||
|
co := L.Newthread()
|
||||||
|
L.Pushcfunction(coroutineFunc)
|
||||||
|
L.Xmove(co, 1)
|
||||||
|
|
||||||
|
var nres c.Int
|
||||||
|
|
||||||
|
c.Printf(c.Str("Resuming coroutine for the first time\n"))
|
||||||
|
result := co.Resume(nil, 0, &nres)
|
||||||
|
if result == lua.YIELD {
|
||||||
|
c.Printf(c.Str("Coroutine yielded\n"))
|
||||||
|
result = co.Resume(nil, 0, &nres)
|
||||||
|
if result == 0 {
|
||||||
|
c.Printf(c.Str("Coroutine finished\n"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Expected output:
|
||||||
|
Resuming coroutine for the first time
|
||||||
|
Coroutine started
|
||||||
|
Coroutine yielded
|
||||||
|
Coroutine finished
|
||||||
|
*/
|
||||||
@@ -36,8 +36,8 @@ func main() {
|
|||||||
// Resume coroutine and handle yields
|
// Resume coroutine and handle yields
|
||||||
for {
|
for {
|
||||||
status = co.Resume(nil, 0, &nres)
|
status = co.Resume(nil, 0, &nres)
|
||||||
c.Printf(c.Str("Resuming coroutine %d...\n"), status)
|
|
||||||
if status == lua.YIELD {
|
if status == lua.YIELD {
|
||||||
|
c.Printf(c.Str("Resuming coroutine %d...\n"), status)
|
||||||
yieldValue := co.Tointeger(-1)
|
yieldValue := co.Tointeger(-1)
|
||||||
c.Printf(c.Str("Yield value: %d\n"), yieldValue)
|
c.Printf(c.Str("Yield value: %d\n"), yieldValue)
|
||||||
co.Pop(1) // Clean up the stack
|
co.Pop(1) // Clean up the stack
|
||||||
@@ -58,3 +58,23 @@ func main() {
|
|||||||
finalStatus := co.Status()
|
finalStatus := co.Status()
|
||||||
c.Printf(c.Str("Final status of coroutine: %d\n"), finalStatus)
|
c.Printf(c.Str("Final status of coroutine: %d\n"), finalStatus)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Expected output:
|
||||||
|
Resuming coroutine...
|
||||||
|
Resuming coroutine 1...
|
||||||
|
Yield value: 1
|
||||||
|
Coroutine is yieldable.
|
||||||
|
Resuming coroutine 1...
|
||||||
|
Yield value: 2
|
||||||
|
Coroutine is yieldable.
|
||||||
|
Resuming coroutine 1...
|
||||||
|
Yield value: 3
|
||||||
|
Coroutine is yieldable.
|
||||||
|
Resuming coroutine 1...
|
||||||
|
Yield value: 4
|
||||||
|
Coroutine is yieldable.
|
||||||
|
Resuming coroutine 1...
|
||||||
|
Yield value: 5
|
||||||
|
Coroutine is yieldable.
|
||||||
|
Final status of coroutine: 0
|
||||||
|
*/
|
||||||
|
|||||||
125
c/lua/_demo/metatable/metatable.go
Normal file
125
c/lua/_demo/metatable/metatable.go
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/lua"
|
||||||
|
)
|
||||||
|
|
||||||
|
func toString(L *lua.State) c.Int {
|
||||||
|
L.Pushstring(c.Str("Hello from metatable!"))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func printStack(L *lua.State, message string) {
|
||||||
|
top := L.Gettop()
|
||||||
|
c.Printf(c.Str("%s - Stack size: %d\n"), c.AllocaCStr(message), c.Int(top))
|
||||||
|
for i := c.Int(1); i <= top; i++ {
|
||||||
|
t := L.Type(i)
|
||||||
|
switch t {
|
||||||
|
case c.Int(lua.STRING):
|
||||||
|
c.Printf(c.Str(" %d: string: %s\n"), c.Int(i), L.Tostring(i))
|
||||||
|
case c.Int(lua.BOOLEAN):
|
||||||
|
c.Printf(c.Str(" %d: boolean: %v\n"), c.Int(i), L.Toboolean(i))
|
||||||
|
case c.Int(lua.NUMBER):
|
||||||
|
c.Printf(c.Str(" %d: number: %f\n"), c.Int(i), L.Tonumber(i))
|
||||||
|
default:
|
||||||
|
c.Printf(c.Str(" %d: %s\n"), c.Int(i), L.Typename(t))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
L := lua.Newstate()
|
||||||
|
defer L.Close()
|
||||||
|
|
||||||
|
L.Openlibs()
|
||||||
|
|
||||||
|
L.Newtable()
|
||||||
|
printStack(L, "After creating main table")
|
||||||
|
|
||||||
|
L.Newtable()
|
||||||
|
printStack(L, "After creating metatable")
|
||||||
|
|
||||||
|
L.Pushcfunction(toString)
|
||||||
|
printStack(L, "After Push CFunction")
|
||||||
|
|
||||||
|
L.Setfield(-2, c.Str("__tostring"))
|
||||||
|
printStack(L, "After setting __tostring")
|
||||||
|
|
||||||
|
if L.Setmetatable(-2) == 0 {
|
||||||
|
c.Printf(c.Str("Failed to set metatable\n"))
|
||||||
|
}
|
||||||
|
printStack(L, "After setting metatable")
|
||||||
|
|
||||||
|
L.Setglobal(c.Str("obj"))
|
||||||
|
printStack(L, "After setting global obj")
|
||||||
|
|
||||||
|
testcode := c.Str(`
|
||||||
|
if obj == nil then
|
||||||
|
print('obj is not defined')
|
||||||
|
else
|
||||||
|
local mt = getmetatable(obj)
|
||||||
|
if not mt then
|
||||||
|
print('Metatable not set')
|
||||||
|
elseif not mt.__tostring then
|
||||||
|
print('__tostring not set in metatable')
|
||||||
|
else
|
||||||
|
print(mt.__tostring(obj))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
`)
|
||||||
|
|
||||||
|
if L.Dostring(testcode) != lua.OK {
|
||||||
|
c.Printf(c.Str("Error: %s\n"), L.Tostring(-1))
|
||||||
|
}
|
||||||
|
|
||||||
|
L.Getglobal(c.Str("obj"))
|
||||||
|
if L.Getmetatable(-1) != 0 {
|
||||||
|
c.Printf(c.Str("Metatable get success\n"))
|
||||||
|
L.Pushstring(c.Str("__tostring"))
|
||||||
|
L.Gettable(-2)
|
||||||
|
if L.Isfunction(-1) {
|
||||||
|
c.Printf(c.Str("__tostring function found in metatable\n"))
|
||||||
|
if L.Iscfunction(-1) != 0 {
|
||||||
|
c.Printf(c.Str("__tostring is a C function\n"))
|
||||||
|
cfunc := L.Tocfunction(-1)
|
||||||
|
if cfunc != nil {
|
||||||
|
c.Printf(c.Str("Successfully retrieved __tostring C function pointer\n"))
|
||||||
|
L.Pushcfunction(cfunc)
|
||||||
|
if L.Call(0, 1) == lua.OK {
|
||||||
|
result := L.Tostring(-1)
|
||||||
|
c.Printf(c.Str("Result of calling __tostring: %s\n"), result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c.Printf(c.Str("__tostring function not found in metatable\n"))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c.Printf(c.Str("No metatable found using GetTable\n"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Expected output:
|
||||||
|
After creating main table - Stack size: 1
|
||||||
|
1: table
|
||||||
|
After creating metatable - Stack size: 2
|
||||||
|
1: table
|
||||||
|
2: table
|
||||||
|
After Push CFunction - Stack size: 3
|
||||||
|
1: table
|
||||||
|
2: table
|
||||||
|
3: function
|
||||||
|
After setting __tostring - Stack size: 2
|
||||||
|
1: table
|
||||||
|
2: table
|
||||||
|
After setting metatable - Stack size: 1
|
||||||
|
1: table
|
||||||
|
After setting global obj - Stack size: 0
|
||||||
|
Hello from metatable!
|
||||||
|
Metatable get success
|
||||||
|
__tostring function found in metatable
|
||||||
|
__tostring is a C function
|
||||||
|
Successfully retrieved __tostring C function pointer
|
||||||
|
Result of calling __tostring: Hello from metatable!
|
||||||
|
*/
|
||||||
121
c/lua/lua.go
121
c/lua/lua.go
@@ -41,17 +41,17 @@ type State struct {
|
|||||||
// ** basic types
|
// ** basic types
|
||||||
// */
|
// */
|
||||||
const (
|
const (
|
||||||
NONE = int(-1)
|
NONE c.Int = -1
|
||||||
NIL = int(0)
|
NIL c.Int = 0
|
||||||
BOOLEAN = int(1)
|
BOOLEAN c.Int = 1
|
||||||
LIGHTUSERDATA = int(2)
|
LIGHTUSERDATA c.Int = 2
|
||||||
NUMBER = int(3)
|
NUMBER c.Int = 3
|
||||||
STRING = int(4)
|
STRING c.Int = 4
|
||||||
TABLE = int(5)
|
TABLE c.Int = 5
|
||||||
FUNCTION = int(6)
|
FUNCTION c.Int = 6
|
||||||
USERDATA = int(7)
|
USERDATA c.Int = 7
|
||||||
THREAD = int(8)
|
THREAD c.Int = 8
|
||||||
UMTYPES = int(9)
|
UMTYPES c.Int = 9
|
||||||
)
|
)
|
||||||
|
|
||||||
// /* minimum Lua stack available to a C function */
|
// /* minimum Lua stack available to a C function */
|
||||||
@@ -78,13 +78,15 @@ type Integer = c.Int
|
|||||||
type Unsigned = c.Uint
|
type Unsigned = c.Uint
|
||||||
|
|
||||||
// /* type for continuation-function contexts */
|
// /* type for continuation-function contexts */
|
||||||
// TODO(zzy): Context may not be c.Int
|
type KContext = c.Pointer
|
||||||
type KContext c.Int
|
|
||||||
|
|
||||||
// /*
|
// /*
|
||||||
// ** Type for C functions registered with Lua
|
// ** Type for C functions registered with Lua
|
||||||
// */
|
// */
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type CFunction func(L *State) c.Int
|
||||||
|
|
||||||
// /*
|
// /*
|
||||||
// ** Type for continuation functions
|
// ** Type for continuation functions
|
||||||
// */
|
// */
|
||||||
@@ -144,7 +146,6 @@ type KFunction func(L *State, status c.Int, ctx KContext) c.Int
|
|||||||
func (L *State) Close() {}
|
func (L *State) Close() {}
|
||||||
|
|
||||||
// State *(lua_newstate) (lua_Alloc f, void *ud);
|
// State *(lua_newstate) (lua_Alloc f, void *ud);
|
||||||
// State *(lua_newthread) (State *L);
|
|
||||||
|
|
||||||
// llgo:link (*State).Newthread C.lua_newthread
|
// llgo:link (*State).Newthread C.lua_newthread
|
||||||
func (L *State) Newthread() *State { return nil }
|
func (L *State) Newthread() *State { return nil }
|
||||||
@@ -185,9 +186,6 @@ func (L *State) Xmove(to *State, n c.Int) {}
|
|||||||
// /*
|
// /*
|
||||||
// ** access functions (stack -> C)
|
// ** access functions (stack -> C)
|
||||||
// */
|
// */
|
||||||
// LUA_API int (lua_isinteger) (State *L, int idx);
|
|
||||||
// llgo:link (*State).Isinteger C.lua_isinteger
|
|
||||||
func (L *State) Isinteger(idx c.Int) c.Int { return 0 }
|
|
||||||
|
|
||||||
// llgo:link (*State).Isnumber C.lua_isnumber
|
// llgo:link (*State).Isnumber C.lua_isnumber
|
||||||
func (L *State) Isnumber(idx c.Int) c.Int { return 0 }
|
func (L *State) Isnumber(idx c.Int) c.Int { return 0 }
|
||||||
@@ -195,11 +193,17 @@ func (L *State) Isnumber(idx c.Int) c.Int { return 0 }
|
|||||||
// llgo:link (*State).Isstring C.lua_isstring
|
// llgo:link (*State).Isstring C.lua_isstring
|
||||||
func (L *State) Isstring(idx c.Int) c.Int { return 0 }
|
func (L *State) Isstring(idx c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
// TODO(zzy):add to demo
|
// llgo:link (*State).Iscfunction C.lua_iscfunction
|
||||||
|
func (L *State) Iscfunction(idx c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
|
// llgo:link (*State).Isinteger C.lua_isinteger
|
||||||
|
func (L *State) Isinteger(idx c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
|
// LUA_API int (lua_isuserdata) (State *L, int idx);
|
||||||
|
|
||||||
// llgo:link (*State).Type C.lua_type
|
// llgo:link (*State).Type C.lua_type
|
||||||
func (L *State) Type(idx c.Int) c.Int { return 0 }
|
func (L *State) Type(idx c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
// TODO(zzy)
|
|
||||||
// llgo:link (*State).Typename C.lua_typename
|
// llgo:link (*State).Typename C.lua_typename
|
||||||
func (L *State) Typename(tp c.Int) *c.Char { return nil }
|
func (L *State) Typename(tp c.Int) *c.Char { return nil }
|
||||||
|
|
||||||
@@ -215,11 +219,11 @@ func (L *State) Toboolean(idx c.Int) bool { return false }
|
|||||||
// llgo:link (*State).Tolstring C.lua_tolstring
|
// llgo:link (*State).Tolstring C.lua_tolstring
|
||||||
func (L *State) Tolstring(idx c.Int, len *c.Ulong) *c.Char { return nil }
|
func (L *State) Tolstring(idx c.Int, len *c.Ulong) *c.Char { return nil }
|
||||||
|
|
||||||
// LUA_API int (lua_iscfunction) (State *L, int idx);
|
|
||||||
// LUA_API int (lua_isuserdata) (State *L, int idx);
|
|
||||||
|
|
||||||
// LUA_API lua_Unsigned (lua_rawlen) (State *L, int idx);
|
// LUA_API lua_Unsigned (lua_rawlen) (State *L, int idx);
|
||||||
// LUA_API lua_CFunction (lua_tocfunction) (State *L, int idx);
|
|
||||||
|
// llgo:link (*State).Tocfunction C.lua_tocfunction
|
||||||
|
func (L *State) Tocfunction(idx c.Int) CFunction { return nil }
|
||||||
|
|
||||||
// LUA_API void *(lua_touserdata) (State *L, int idx);
|
// LUA_API void *(lua_touserdata) (State *L, int idx);
|
||||||
// LUA_API State *(lua_tothread) (State *L, int idx);
|
// LUA_API State *(lua_tothread) (State *L, int idx);
|
||||||
// LUA_API const void *(lua_topointer) (State *L, int idx);
|
// LUA_API const void *(lua_topointer) (State *L, int idx);
|
||||||
@@ -240,24 +244,21 @@ func (L *State) Pushnumber(n Number) {}
|
|||||||
// llgo:link (*State).Pushinteger C.lua_pushinteger
|
// llgo:link (*State).Pushinteger C.lua_pushinteger
|
||||||
func (L *State) Pushinteger(n Integer) {}
|
func (L *State) Pushinteger(n Integer) {}
|
||||||
|
|
||||||
// llgo:link (*State).Pushstring C.lua_pushstring
|
|
||||||
func (L *State) Pushstring(s *c.Char) *c.Char {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// llgo:link (*State).Pushlstring C.lua_pushlstring
|
// llgo:link (*State).Pushlstring C.lua_pushlstring
|
||||||
func (L *State) Pushlstring(s *c.Char, len c.Ulong) *c.Char {
|
func (L *State) Pushlstring(s *c.Char, len c.Ulong) *c.Char { return nil }
|
||||||
return nil
|
|
||||||
}
|
// llgo:link (*State).Pushstring C.lua_pushstring
|
||||||
|
func (L *State) Pushstring(s *c.Char) *c.Char { return nil }
|
||||||
|
|
||||||
// llgo:link (*State).Pushfstring C.lua_pushfstring
|
// llgo:link (*State).Pushfstring C.lua_pushfstring
|
||||||
func (L *State) Pushfstring(format *c.Char, __llgo_va_list ...any) *c.Char { return nil }
|
func (L *State) Pushfstring(format *c.Char, __llgo_va_list ...any) *c.Char { return nil }
|
||||||
|
|
||||||
|
// llgo:link (*State).Pushcclosure C.lua_pushcclosure
|
||||||
|
func (L *State) Pushcclosure(fn CFunction, n c.Int) {}
|
||||||
|
|
||||||
// llgo:link (*State).Pushboolean C.lua_pushboolean
|
// llgo:link (*State).Pushboolean C.lua_pushboolean
|
||||||
func (L *State) Pushboolean(b c.Int) {}
|
func (L *State) Pushboolean(b c.Int) {}
|
||||||
|
|
||||||
//const char *(lua_pushvfstring) (State *L, const char *fmt,va_list argp);
|
|
||||||
//void (lua_pushcclosure) (State *L, lua_CFunction fn, int n);
|
|
||||||
//void (lua_pushlightuserdata) (State *L, void *p);
|
//void (lua_pushlightuserdata) (State *L, void *p);
|
||||||
//int (lua_pushthread) (State *L);
|
//int (lua_pushthread) (State *L);
|
||||||
|
|
||||||
@@ -274,23 +275,25 @@ func (L *State) Gettable(idx c.Int) c.Int { return 0 }
|
|||||||
// llgo:link (*State).Getfield C.lua_getfield
|
// llgo:link (*State).Getfield C.lua_getfield
|
||||||
func (L *State) Getfield(idx c.Int, k *c.Char) c.Int { return 0 }
|
func (L *State) Getfield(idx c.Int, k *c.Char) c.Int { return 0 }
|
||||||
|
|
||||||
// llgo:link (*State).Createtable C.lua_createtable
|
|
||||||
func (L *State) Createtable(narr c.Int, nrec c.Int) {}
|
|
||||||
|
|
||||||
// LUA_API int (lua_geti) (State *L, int idx, lua_Integer n);
|
// LUA_API int (lua_geti) (State *L, int idx, lua_Integer n);
|
||||||
// LUA_API int (lua_rawget) (State *L, int idx);
|
// LUA_API int (lua_rawget) (State *L, int idx);
|
||||||
// LUA_API int (lua_rawgeti) (State *L, int idx, lua_Integer n);
|
// LUA_API int (lua_rawgeti) (State *L, int idx, lua_Integer n);
|
||||||
// LUA_API int (lua_rawgetp) (State *L, int idx, const void *p);
|
// LUA_API int (lua_rawgetp) (State *L, int idx, const void *p);
|
||||||
|
|
||||||
|
// llgo:link (*State).Createtable C.lua_createtable
|
||||||
|
func (L *State) Createtable(narr c.Int, nrec c.Int) {}
|
||||||
|
|
||||||
// LUA_API void *(lua_newuserdatauv) (State *L, size_t sz, int nuvalue);
|
// LUA_API void *(lua_newuserdatauv) (State *L, size_t sz, int nuvalue);
|
||||||
// LUA_API int (lua_getmetatable) (State *L, int objindex);
|
|
||||||
|
// llgo:link (*State).Getmetatable C.lua_getmetatable
|
||||||
|
func (L *State) Getmetatable(objindex c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
// LUA_API int (lua_getiuservalue) (State *L, int idx, int n);
|
// LUA_API int (lua_getiuservalue) (State *L, int idx, int n);
|
||||||
|
|
||||||
// /*
|
// /*
|
||||||
// ** set functions (stack -> Lua)
|
// ** set functions (stack -> Lua)
|
||||||
// */
|
// */
|
||||||
|
|
||||||
// TODO(zzy):add to demo
|
|
||||||
// llgo:link (*State).Setglobal C.lua_setglobal
|
// llgo:link (*State).Setglobal C.lua_setglobal
|
||||||
func (L *State) Setglobal(name *c.Char) {}
|
func (L *State) Setglobal(name *c.Char) {}
|
||||||
|
|
||||||
@@ -304,25 +307,34 @@ func (L *State) Setfield(idx c.Int, k *c.Char) {}
|
|||||||
//void (lua_rawset) (State *L, int idx);
|
//void (lua_rawset) (State *L, int idx);
|
||||||
//void (lua_rawseti) (State *L, int idx, lua_Integer n);
|
//void (lua_rawseti) (State *L, int idx, lua_Integer n);
|
||||||
//void (lua_rawsetp) (State *L, int idx, const void *p);
|
//void (lua_rawsetp) (State *L, int idx, const void *p);
|
||||||
//int (lua_setmetatable) (State *L, int objindex);
|
|
||||||
|
// llgo:link (*State).Setmetatable C.lua_setmetatable
|
||||||
|
func (L *State) Setmetatable(objindex c.Int) c.Int { return 0 }
|
||||||
|
|
||||||
//int (lua_setiuservalue) (State *L, int idx, int n);
|
//int (lua_setiuservalue) (State *L, int idx, int n);
|
||||||
|
|
||||||
// /*
|
// /*
|
||||||
// ** 'load' and 'call' functions (load and run Lua code)
|
// ** 'load' and 'call' functions (load and run Lua code)
|
||||||
// */
|
// */
|
||||||
|
|
||||||
|
// llgo:link (*State).Callk C.lua_callk
|
||||||
|
func (L *State) Callk(nargs c.Int, nresults c.Int, ctx KContext, k KFunction) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (L *State) Call(nargs c.Int, nresults c.Int) c.Int {
|
||||||
|
return L.Callk(nargs, nresults, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
// llgo:link (*State).Pcallk C.lua_pcallk
|
// llgo:link (*State).Pcallk C.lua_pcallk
|
||||||
func (L *State) Pcallk(nargs c.Int, nresults c.Int, errfunc c.Int, ctx KContext, k *KFunction) c.Int {
|
func (L *State) Pcallk(nargs c.Int, nresults c.Int, errfunc c.Int, ctx KContext, k KFunction) c.Int {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (L *State) Pcall(nargs c.Int, nresults c.Int, errfunc c.Int) c.Int {
|
func (L *State) Pcall(nargs c.Int, nresults c.Int, errfunc c.Int) c.Int {
|
||||||
return L.Pcallk(nargs, nresults, errfunc, KContext(c.Int(0)), nil)
|
return L.Pcallk(nargs, nresults, errfunc, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// void (lua_callk) (State *L, int nargs, int nresults, lua_KContext ctx, lua_KFunction k);
|
|
||||||
// #define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL)
|
|
||||||
|
|
||||||
// int (lua_load) (State *L, lua_Reader reader, void *dt, const char *chunkname, const char *mode);
|
// int (lua_load) (State *L, lua_Reader reader, void *dt, const char *chunkname, const char *mode);
|
||||||
|
|
||||||
// int (lua_dump) (State *L, lua_Writer writer, void *data, int strip);
|
// int (lua_dump) (State *L, lua_Writer writer, void *data, int strip);
|
||||||
@@ -340,9 +352,9 @@ func (L *State) Status() c.Int { return 0 }
|
|||||||
// llgo:link (*State).Isyieldable C.lua_isyieldable
|
// llgo:link (*State).Isyieldable C.lua_isyieldable
|
||||||
func (L *State) Isyieldable() c.Int { return 0 }
|
func (L *State) Isyieldable() c.Int { return 0 }
|
||||||
|
|
||||||
// TODO(zzy)
|
// llgo:link (*State).Yieldk C.lua_yieldk
|
||||||
// int (lua_yieldk) (State *L, int nresults, lua_KContext ctx, lua_KFunction k);
|
func (L *State) Yieldk(nresults c.Int, ctx KContext, k KFunction) c.Int { return 0 }
|
||||||
// #define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL)
|
func (L *State) Yield(nresults c.Int) c.Int { return L.Yieldk(nresults, nil, nil) }
|
||||||
|
|
||||||
// /*
|
// /*
|
||||||
// ** Warning-related functions
|
// ** Warning-related functions
|
||||||
@@ -396,11 +408,17 @@ func (L *State) Next(idx c.Int) c.Int { return 0 }
|
|||||||
// ** ===============================================================
|
// ** ===============================================================
|
||||||
// */
|
// */
|
||||||
|
|
||||||
|
// #define lua_getextraspace(L) ((void *)((char *)(L) - LUA_EXTRASPACE))
|
||||||
|
|
||||||
func (L *State) Tonumber(idx c.Int) Number { return L.Tonumberx(idx, nil) }
|
func (L *State) Tonumber(idx c.Int) Number { return L.Tonumberx(idx, nil) }
|
||||||
func (L *State) Tostring(idx c.Int) *c.Char { return L.Tolstring(idx, nil) }
|
func (L *State) Tostring(idx c.Int) *c.Char { return L.Tolstring(idx, nil) }
|
||||||
func (L *State) Tointeger(idx c.Int) Integer { return L.Tointegerx(idx, nil) }
|
func (L *State) Tointeger(idx c.Int) Integer { return L.Tointegerx(idx, nil) }
|
||||||
func (L *State) Pop(n c.Int) { L.Settop(-(n) - 1) }
|
func (L *State) Pop(n c.Int) { L.Settop(-(n) - 1) }
|
||||||
func (L *State) Newtable() { L.Createtable(0, 0) }
|
func (L *State) Newtable() { L.Createtable(0, 0) }
|
||||||
|
|
||||||
|
// #define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))
|
||||||
|
func (L *State) Pushcfunction(f CFunction) { L.Pushcclosure(f, 0) }
|
||||||
|
|
||||||
func (L *State) Isfunction(n c.Int) bool { return L.Type(n) == c.Int(FUNCTION) }
|
func (L *State) Isfunction(n c.Int) bool { return L.Type(n) == c.Int(FUNCTION) }
|
||||||
func (L *State) Istable(n c.Int) bool { return L.Type(n) == c.Int(TABLE) }
|
func (L *State) Istable(n c.Int) bool { return L.Type(n) == c.Int(TABLE) }
|
||||||
func (L *State) Islightuserdata(n c.Int) bool { return L.Type(n) == c.Int(LIGHTUSERDATA) }
|
func (L *State) Islightuserdata(n c.Int) bool { return L.Type(n) == c.Int(LIGHTUSERDATA) }
|
||||||
@@ -410,20 +428,11 @@ func (L *State) Isthread(n c.Int) bool { return L.Type(n) == c.Int(THREAD
|
|||||||
func (L *State) Isnone(n c.Int) bool { return L.Type(n) == c.Int(NONE) }
|
func (L *State) Isnone(n c.Int) bool { return L.Type(n) == c.Int(NONE) }
|
||||||
func (L *State) Isnoneornil(n c.Int) bool { return L.Type(n) <= 0 }
|
func (L *State) Isnoneornil(n c.Int) bool { return L.Type(n) <= 0 }
|
||||||
|
|
||||||
// #define lua_getextraspace(L) ((void *)((char *)(L) - LUA_EXTRASPACE))
|
|
||||||
|
|
||||||
// #define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))
|
|
||||||
|
|
||||||
// #define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0)
|
|
||||||
|
|
||||||
// #define lua_pushliteral(L, s) lua_pushstring(L, "" s)
|
// #define lua_pushliteral(L, s) lua_pushstring(L, "" s)
|
||||||
|
|
||||||
// #define lua_pushglobaltable(L) ((void)lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS))
|
// #define lua_pushglobaltable(L) ((void)lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS))
|
||||||
|
|
||||||
// #define lua_insert(L,idx) lua_rotate(L, (idx), 1)
|
// #define lua_insert(L,idx) lua_rotate(L, (idx), 1)
|
||||||
|
|
||||||
// #define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1))
|
// #define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1))
|
||||||
|
|
||||||
// #define lua_replace(L,idx) (lua_copy(L, -1, (idx)), lua_pop(L, 1))
|
// #define lua_replace(L,idx) (lua_copy(L, -1, (idx)), lua_pop(L, 1))
|
||||||
|
|
||||||
// /* }============================================================== */
|
// /* }============================================================== */
|
||||||
|
|||||||
85
c/openssl/md5.go
Normal file
85
c/openssl/md5.go
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* 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 openssl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const (
|
||||||
|
MD5_CBLOCK = 64
|
||||||
|
MD5_LBLOCK = MD5_CBLOCK / 4
|
||||||
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type MD5_LONG = c.Uint
|
||||||
|
|
||||||
|
type MD5_CTX struct {
|
||||||
|
A, B, C, D MD5_LONG
|
||||||
|
Nl, Nh MD5_LONG
|
||||||
|
Data [MD5_LBLOCK]MD5_LONG
|
||||||
|
Num c.Uint
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int MD5_Init(MD5_CTX *c);
|
||||||
|
//
|
||||||
|
// llgo:link (*MD5_CTX).Init C.MD5_Init
|
||||||
|
func (c *MD5_CTX) Init() c.Int { return 0 }
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int MD5_Update(MD5_CTX *c, const void *data, size_t len);
|
||||||
|
//
|
||||||
|
// llgo:link (*MD5_CTX).Update C.MD5_Update
|
||||||
|
func (c *MD5_CTX) Update(data unsafe.Pointer, n uintptr) c.Int { return 0 }
|
||||||
|
|
||||||
|
func (c *MD5_CTX) UpdateBytes(data []byte) c.Int {
|
||||||
|
return c.Update(unsafe.Pointer(unsafe.SliceData(data)), uintptr(len(data)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MD5_CTX) UpdateString(data string) c.Int {
|
||||||
|
return c.Update(unsafe.Pointer(unsafe.StringData(data)), uintptr(len(data)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int MD5_Final(unsigned char *md, MD5_CTX *c);
|
||||||
|
//
|
||||||
|
//go:linkname md5Final C.MD5_Final
|
||||||
|
func md5Final(md *byte, c *MD5_CTX) c.Int
|
||||||
|
|
||||||
|
func (c *MD5_CTX) Final(md *byte) c.Int {
|
||||||
|
return md5Final(md, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 unsigned char *MD5(const unsigned char *d, size_t n, unsigned char *md);
|
||||||
|
//
|
||||||
|
//go:linkname MD5 C.MD5
|
||||||
|
func MD5(data unsafe.Pointer, n uintptr, md *byte) *byte
|
||||||
|
|
||||||
|
func MD5Bytes(data []byte, md *byte) *byte {
|
||||||
|
return MD5(unsafe.Pointer(unsafe.SliceData(data)), uintptr(len(data)), md)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MD5String(data string, md *byte) *byte {
|
||||||
|
return MD5(unsafe.Pointer(unsafe.StringData(data)), uintptr(len(data)), md)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 void MD5_Transform(MD5_CTX *c, const unsigned char *b);
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
23
c/openssl/openssl.go
Normal file
23
c/openssl/openssl.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* 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 openssl
|
||||||
|
|
||||||
|
const (
|
||||||
|
LLGoPackage = "link: $(pkg-config --libs openssl); -lssl -lcrypto"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
94
c/openssl/sha1.go
Normal file
94
c/openssl/sha1.go
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* 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 openssl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SHA_DIGEST_LENGTH = 20
|
||||||
|
SHA_LBLOCK = 16
|
||||||
|
SHA_CBLOCK = (SHA_LBLOCK * 4)
|
||||||
|
SHA_LAST_BLOCK = (SHA_CBLOCK - 8)
|
||||||
|
|
||||||
|
SHA256_CBLOCK = (SHA_LBLOCK * 4)
|
||||||
|
SHA256_192_DIGEST_LENGTH = 24
|
||||||
|
SHA224_DIGEST_LENGTH = 28
|
||||||
|
SHA256_DIGEST_LENGTH = 32
|
||||||
|
SHA384_DIGEST_LENGTH = 48
|
||||||
|
SHA512_DIGEST_LENGTH = 64
|
||||||
|
SHA512_CBLOCK = (SHA_LBLOCK * 8)
|
||||||
|
)
|
||||||
|
|
||||||
|
type SHA_LONG64 = c.UlongLong
|
||||||
|
|
||||||
|
type SHA_LONG = c.Uint
|
||||||
|
|
||||||
|
type SHA_CTX struct {
|
||||||
|
H0, H1, H2, H3, H4 SHA_LONG
|
||||||
|
Nl, Nh SHA_LONG
|
||||||
|
Data [SHA_LBLOCK]SHA_LONG
|
||||||
|
Num c.Uint
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int SHA1_Init(SHA_CTX *c);
|
||||||
|
//
|
||||||
|
// llgo:link (*SHA_CTX).Init C.SHA1_Init
|
||||||
|
func (c *SHA_CTX) Init() c.Int { return 0 }
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int SHA1_Update(SHA_CTX *c, const void *data, size_t len);
|
||||||
|
//
|
||||||
|
// llgo:link (*SHA_CTX).Update C.SHA1_Update
|
||||||
|
func (c *SHA_CTX) Update(data unsafe.Pointer, n uintptr) c.Int { return 0 }
|
||||||
|
|
||||||
|
func (c *SHA_CTX) UpdateBytes(data []byte) c.Int {
|
||||||
|
return c.Update(unsafe.Pointer(unsafe.SliceData(data)), uintptr(len(data)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SHA_CTX) UpdateString(data string) c.Int {
|
||||||
|
return c.Update(unsafe.Pointer(unsafe.StringData(data)), uintptr(len(data)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int SHA1_Final(unsigned char *md, SHA_CTX *c);
|
||||||
|
//
|
||||||
|
//go:linkname sha1Final C.SHA1_Final
|
||||||
|
func sha1Final(md *byte, c *SHA_CTX) c.Int
|
||||||
|
|
||||||
|
func (c *SHA_CTX) Final(md *byte) c.Int {
|
||||||
|
return sha1Final(md, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 void SHA1_Transform(SHA_CTX *c, const unsigned char *data);
|
||||||
|
//
|
||||||
|
// llgo:link (*SHA_CTX).Transform C.SHA1_Transform
|
||||||
|
func (c *SHA_CTX) Transform(data *byte) {}
|
||||||
|
|
||||||
|
// unsigned char *SHA1(const unsigned char *d, size_t n, unsigned char *md);
|
||||||
|
//
|
||||||
|
//go:linkname SHA1 C.SHA1
|
||||||
|
func SHA1(data unsafe.Pointer, n uintptr, md *byte) *byte
|
||||||
|
|
||||||
|
func SHA1Bytes(data []byte, md *byte) *byte {
|
||||||
|
return SHA1(unsafe.Pointer(unsafe.SliceData(data)), uintptr(len(data)), md)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SHA1String(data string, md *byte) *byte {
|
||||||
|
return SHA1(unsafe.Pointer(unsafe.StringData(data)), uintptr(len(data)), md)
|
||||||
|
}
|
||||||
117
c/openssl/sha256.go
Normal file
117
c/openssl/sha256.go
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* 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 openssl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SHA256_CTX struct {
|
||||||
|
H [8]SHA_LONG
|
||||||
|
Nl, Nh SHA_LONG
|
||||||
|
Data [SHA_LBLOCK]SHA_LONG
|
||||||
|
Num, MdLen c.Uint
|
||||||
|
}
|
||||||
|
|
||||||
|
type SHA224_CTX SHA256_CTX
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int SHA224_Init(SHA256_CTX *c);
|
||||||
|
//
|
||||||
|
// llgo:link (*SHA224_CTX).Init C.SHA224_Init
|
||||||
|
func (c *SHA224_CTX) Init() c.Int { return 0 }
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int SHA224_Update(SHA256_CTX *c, const void *data, size_t len);
|
||||||
|
//
|
||||||
|
// llgo:link (*SHA224_CTX).Update C.SHA224_Update
|
||||||
|
func (c *SHA224_CTX) Update(data unsafe.Pointer, n uintptr) c.Int { return 0 }
|
||||||
|
|
||||||
|
func (c *SHA224_CTX) UpdateBytes(data []byte) c.Int {
|
||||||
|
return c.Update(unsafe.Pointer(unsafe.SliceData(data)), uintptr(len(data)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SHA224_CTX) UpdateString(data string) c.Int {
|
||||||
|
return c.Update(unsafe.Pointer(unsafe.StringData(data)), uintptr(len(data)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int SHA224_Final(unsigned char *md, SHA256_CTX *c);
|
||||||
|
//
|
||||||
|
//go:linkname sha224Final C.SHA224_Final
|
||||||
|
func sha224Final(md *byte, c *SHA224_CTX) c.Int
|
||||||
|
|
||||||
|
func (c *SHA224_CTX) Final(md *byte) c.Int {
|
||||||
|
return sha224Final(md, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int SHA256_Init(SHA256_CTX *c);
|
||||||
|
//
|
||||||
|
// llgo:link (*SHA256_CTX).Init C.SHA256_Init
|
||||||
|
func (c *SHA256_CTX) Init() c.Int { return 0 }
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int SHA256_Update(SHA256_CTX *c, const void *data, size_t len);
|
||||||
|
//
|
||||||
|
// llgo:link (*SHA256_CTX).Update C.SHA256_Update
|
||||||
|
func (c *SHA256_CTX) Update(data unsafe.Pointer, n uintptr) c.Int { return 0 }
|
||||||
|
|
||||||
|
func (c *SHA256_CTX) UpdateBytes(data []byte) c.Int {
|
||||||
|
return c.Update(unsafe.Pointer(unsafe.SliceData(data)), uintptr(len(data)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SHA256_CTX) UpdateString(data string) c.Int {
|
||||||
|
return c.Update(unsafe.Pointer(unsafe.StringData(data)), uintptr(len(data)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int SHA256_Final(unsigned char *md, SHA256_CTX *c);
|
||||||
|
//
|
||||||
|
//go:linkname sha256Final C.SHA256_Final
|
||||||
|
func sha256Final(md *byte, c *SHA256_CTX) c.Int
|
||||||
|
|
||||||
|
func (c *SHA256_CTX) Final(md *byte) c.Int {
|
||||||
|
return sha256Final(md, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 void SHA256_Transform(SHA256_CTX *c, const unsigned char *data);
|
||||||
|
//
|
||||||
|
// llgo:link (*SHA256_CTX).Transform C.SHA256_Transform
|
||||||
|
func (c *SHA256_CTX) Transform(data *byte) {}
|
||||||
|
|
||||||
|
// unsigned char *SHA224(const unsigned char *d, size_t n, unsigned char *md);
|
||||||
|
//
|
||||||
|
//go:linkname SHA224 C.SHA224
|
||||||
|
func SHA224(data unsafe.Pointer, n uintptr, md *byte) *byte
|
||||||
|
|
||||||
|
func SHA224Bytes(data []byte, md *byte) *byte {
|
||||||
|
return SHA224(unsafe.Pointer(unsafe.SliceData(data)), uintptr(len(data)), md)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SHA224String(data string, md *byte) *byte {
|
||||||
|
return SHA224(unsafe.Pointer(unsafe.StringData(data)), uintptr(len(data)), md)
|
||||||
|
}
|
||||||
|
|
||||||
|
// unsigned char *SHA256(const unsigned char *d, size_t n, unsigned char *md);
|
||||||
|
//
|
||||||
|
//go:linkname SHA256 C.SHA256
|
||||||
|
func SHA256(data unsafe.Pointer, n uintptr, md *byte) *byte
|
||||||
|
|
||||||
|
func SHA256Bytes(data []byte, md *byte) *byte {
|
||||||
|
return SHA256(unsafe.Pointer(unsafe.SliceData(data)), uintptr(len(data)), md)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SHA256String(data string, md *byte) *byte {
|
||||||
|
return SHA256(unsafe.Pointer(unsafe.StringData(data)), uintptr(len(data)), md)
|
||||||
|
}
|
||||||
115
c/openssl/sha512.go
Normal file
115
c/openssl/sha512.go
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* 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 openssl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SHA512_CTX struct {
|
||||||
|
H [8]SHA_LONG64
|
||||||
|
N1, Nh SHA_LONG64
|
||||||
|
D [SHA_LBLOCK]SHA_LONG64
|
||||||
|
Num, MdLen c.Uint
|
||||||
|
}
|
||||||
|
|
||||||
|
type SHA384_CTX SHA512_CTX
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int SHA384_Init(SHA512_CTX *c);
|
||||||
|
//
|
||||||
|
// llgo:link (*SHA384_CTX).Init C.SHA384_Init
|
||||||
|
func (c *SHA384_CTX) Init() c.Int { return 0 }
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int SHA384_Update(SHA512_CTX *c, const void *data, size_t len);
|
||||||
|
//
|
||||||
|
// llgo:link (*SHA384_CTX).Update C.SHA384_Update
|
||||||
|
func (c *SHA384_CTX) Update(data unsafe.Pointer, n uintptr) c.Int { return 0 }
|
||||||
|
|
||||||
|
func (c *SHA384_CTX) UpdateBytes(data []byte) c.Int {
|
||||||
|
return c.Update(unsafe.Pointer(unsafe.SliceData(data)), uintptr(len(data)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SHA384_CTX) UpdateString(data string) c.Int {
|
||||||
|
return c.Update(unsafe.Pointer(unsafe.StringData(data)), uintptr(len(data)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int SHA384_Final(unsigned char *md, SHA512_CTX *c);
|
||||||
|
//
|
||||||
|
//go:linkname sha384Final C.SHA384_Final
|
||||||
|
func sha384Final(md *byte, c *SHA384_CTX) c.Int
|
||||||
|
|
||||||
|
func (c *SHA384_CTX) Final(md *byte) c.Int {
|
||||||
|
return sha384Final(md, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int SHA512_Init(SHA512_CTX *c);
|
||||||
|
//
|
||||||
|
// llgo:link (*SHA512_CTX).Init C.SHA512_Init
|
||||||
|
func (c *SHA512_CTX) Init() c.Int { return 0 }
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int SHA512_Update(SHA512_CTX *c, const void *data, size_t len);
|
||||||
|
//
|
||||||
|
// llgo:link (*SHA512_CTX).Update C.SHA512_Update
|
||||||
|
func (c *SHA512_CTX) Update(data unsafe.Pointer, n uintptr) c.Int { return 0 }
|
||||||
|
func (c *SHA512_CTX) UpdateBytes(data []byte) c.Int {
|
||||||
|
return c.Update(unsafe.Pointer(unsafe.SliceData(data)), uintptr(len(data)))
|
||||||
|
}
|
||||||
|
func (c *SHA512_CTX) UpdateString(data string) c.Int {
|
||||||
|
return c.Update(unsafe.Pointer(unsafe.StringData(data)), uintptr(len(data)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 int SHA512_Final(unsigned char *md, SHA512_CTX *c);
|
||||||
|
//
|
||||||
|
//go:linkname sha512Final C.SHA512_Final
|
||||||
|
func sha512Final(md *byte, c *SHA512_CTX) c.Int
|
||||||
|
|
||||||
|
func (c *SHA512_CTX) Final(md *byte) c.Int {
|
||||||
|
return sha512Final(md, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSSL_DEPRECATEDIN_3_0 void SHA512_Transform(SHA512_CTX *c, const unsigned char *data);
|
||||||
|
//
|
||||||
|
// llgo:link (*SHA512_CTX).Transform C.SHA512_Transform
|
||||||
|
func (c *SHA512_CTX) Transform(data *byte) {}
|
||||||
|
|
||||||
|
// unsigned char *SHA384(const unsigned char *d, size_t n, unsigned char *md);
|
||||||
|
//
|
||||||
|
//go:linkname SHA384 C.SHA384
|
||||||
|
func SHA384(data unsafe.Pointer, n uintptr, md *byte) *byte
|
||||||
|
|
||||||
|
func SHA384Bytes(data []byte, md *byte) *byte {
|
||||||
|
return SHA384(unsafe.Pointer(unsafe.SliceData(data)), uintptr(len(data)), md)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SHA384String(data string, md *byte) *byte {
|
||||||
|
return SHA384(unsafe.Pointer(unsafe.StringData(data)), uintptr(len(data)), md)
|
||||||
|
}
|
||||||
|
|
||||||
|
// unsigned char *SHA512(const unsigned char *d, size_t n, unsigned char *md);
|
||||||
|
//
|
||||||
|
//go:linkname SHA512 C.SHA512
|
||||||
|
func SHA512(data unsafe.Pointer, n uintptr, md *byte) *byte
|
||||||
|
|
||||||
|
func SHA512Bytes(data []byte, md *byte) *byte {
|
||||||
|
return SHA512(unsafe.Pointer(unsafe.SliceData(data)), uintptr(len(data)), md)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SHA512String(data string, md *byte) *byte {
|
||||||
|
return SHA512(unsafe.Pointer(unsafe.StringData(data)), uintptr(len(data)), md)
|
||||||
|
}
|
||||||
@@ -5,3 +5,15 @@
|
|||||||
pthread_once_t llgoSyncOnceInitVal = PTHREAD_ONCE_INIT;
|
pthread_once_t llgoSyncOnceInitVal = PTHREAD_ONCE_INIT;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// wrap return type to void
|
||||||
|
void wrap_pthread_mutex_lock(pthread_mutex_t *mutex) {
|
||||||
|
pthread_mutex_lock(mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// wrap return type to void
|
||||||
|
void wrap_pthread_mutex_unlock(pthread_mutex_t *mutex) {
|
||||||
|
pthread_mutex_unlock(mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -76,18 +76,14 @@ func (m *Mutex) Init(attr *MutexAttr) c.Int { return 0 }
|
|||||||
// llgo:link (*Mutex).Destroy C.pthread_mutex_destroy
|
// llgo:link (*Mutex).Destroy C.pthread_mutex_destroy
|
||||||
func (m *Mutex) Destroy() {}
|
func (m *Mutex) Destroy() {}
|
||||||
|
|
||||||
func (m *Mutex) Lock() { m.lockInternal() }
|
|
||||||
|
|
||||||
// llgo:link (*Mutex).lockInternal C.pthread_mutex_lock
|
|
||||||
func (m *Mutex) lockInternal() c.Int { return 0 }
|
|
||||||
|
|
||||||
// llgo:link (*Mutex).TryLock C.pthread_mutex_trylock
|
// llgo:link (*Mutex).TryLock C.pthread_mutex_trylock
|
||||||
func (m *Mutex) TryLock() c.Int { return 0 }
|
func (m *Mutex) TryLock() c.Int { return 0 }
|
||||||
|
|
||||||
func (m *Mutex) Unlock() { m.unlockInternal() }
|
// llgo:link (*Mutex).Lock C.wrap_pthread_mutex_lock
|
||||||
|
func (m *Mutex) Lock() {}
|
||||||
|
|
||||||
// llgo:link (*Mutex).unlockInternal C.pthread_mutex_unlock
|
// llgo:link (*Mutex).Unlock C.wrap_pthread_mutex_unlock
|
||||||
func (m *Mutex) unlockInternal() c.Int { return 0 }
|
func (m *Mutex) Unlock() {}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -44,9 +44,6 @@ func Longjmp(env *JmpBuf, val c.Int)
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
//go:linkname Sigsetjmp C.sigsetjmp
|
|
||||||
func Sigsetjmp(env *SigjmpBuf, savemask c.Int) c.Int
|
|
||||||
|
|
||||||
//go:linkname Siglongjmp C.siglongjmp
|
//go:linkname Siglongjmp C.siglongjmp
|
||||||
func Siglongjmp(env *SigjmpBuf, val c.Int)
|
func Siglongjmp(env *SigjmpBuf, val c.Int)
|
||||||
|
|
||||||
|
|||||||
12
c/setjmp/setjmp_linux.go
Normal file
12
c/setjmp/setjmp_linux.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
//go:build linux
|
||||||
|
|
||||||
|
package setjmp
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:linkname Sigsetjmp C.__sigsetjmp
|
||||||
|
func Sigsetjmp(env *SigjmpBuf, savemask c.Int) c.Int
|
||||||
12
c/setjmp/setjmp_other.go
Normal file
12
c/setjmp/setjmp_other.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
//go:build !linux
|
||||||
|
|
||||||
|
package setjmp
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:linkname Sigsetjmp C.sigsetjmp
|
||||||
|
func Sigsetjmp(env *SigjmpBuf, savemask c.Int) c.Int
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
package syscall
|
package syscall
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LLGoPackage = "decl"
|
LLGoPackage = "noinit"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Errno = uintptr
|
type Errno = uintptr
|
||||||
@@ -25,3 +25,8 @@ type Errno = uintptr
|
|||||||
// A Signal is a number describing a process signal.
|
// A Signal is a number describing a process signal.
|
||||||
// It implements the os.Signal interface.
|
// It implements the os.Signal interface.
|
||||||
type Signal = int
|
type Signal = int
|
||||||
|
|
||||||
|
// Unix returns the time stored in ts as seconds plus nanoseconds.
|
||||||
|
func (ts *Timespec) Unix() (sec int64, nsec int64) {
|
||||||
|
return int64(ts.Sec), int64(ts.Nsec)
|
||||||
|
}
|
||||||
|
|||||||
11
c/zlib/_demo/crc32demo/crc.go
Normal file
11
c/zlib/_demo/crc32demo/crc.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c/zlib"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Printf("%08x\n", zlib.Crc32ZString(0, "Hello world"))
|
||||||
|
}
|
||||||
170
c/zlib/zlib.go
170
c/zlib/zlib.go
@@ -17,7 +17,7 @@
|
|||||||
package zlib
|
package zlib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/goplus/llgo/c"
|
"github.com/goplus/llgo/c"
|
||||||
)
|
)
|
||||||
@@ -76,17 +76,185 @@ const (
|
|||||||
DEFLATED = 8
|
DEFLATED = 8
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/*
|
||||||
|
ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
|
||||||
|
|
||||||
|
compressBound() returns an upper bound on the compressed size after
|
||||||
|
compress() or compress2() on sourceLen bytes. It would be used before a
|
||||||
|
compress() or compress2() call to allocate the destination buffer.
|
||||||
|
*/
|
||||||
//go:linkname CompressBound C.compressBound
|
//go:linkname CompressBound C.compressBound
|
||||||
func CompressBound(sourceLen c.Ulong) c.Ulong
|
func CompressBound(sourceLen c.Ulong) c.Ulong
|
||||||
|
|
||||||
|
/*
|
||||||
|
ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen,
|
||||||
|
const Bytef *source, uLong sourceLen));
|
||||||
|
|
||||||
|
Compresses the source buffer into the destination buffer. sourceLen is
|
||||||
|
the byte length of the source buffer. Upon entry, destLen is the total size
|
||||||
|
of the destination buffer, which must be at least the value returned by
|
||||||
|
compressBound(sourceLen). Upon exit, destLen is the actual size of the
|
||||||
|
compressed data. compress() is equivalent to compress2() with a level
|
||||||
|
parameter of Z_DEFAULT_COMPRESSION.
|
||||||
|
|
||||||
|
compress returns Z_OK if success, Z_MEM_ERROR if there was not
|
||||||
|
enough memory, Z_BUF_ERROR if there was not enough room in the output
|
||||||
|
buffer.
|
||||||
|
*/
|
||||||
//go:linkname Compress C.compress
|
//go:linkname Compress C.compress
|
||||||
func Compress(dest *byte, destLen *c.Ulong, source *byte, sourceLen c.Ulong) c.Int
|
func Compress(dest *byte, destLen *c.Ulong, source *byte, sourceLen c.Ulong) c.Int
|
||||||
|
|
||||||
|
/*
|
||||||
|
ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen,
|
||||||
|
const Bytef *source, uLong sourceLen, int level));
|
||||||
|
|
||||||
|
Compresses the source buffer into the destination buffer. The level
|
||||||
|
parameter has the same meaning as in deflateInit. sourceLen is the byte
|
||||||
|
length of the source buffer. Upon entry, destLen is the total size of the
|
||||||
|
destination buffer, which must be at least the value returned by
|
||||||
|
compressBound(sourceLen). Upon exit, destLen is the actual size of the
|
||||||
|
compressed data.
|
||||||
|
|
||||||
|
compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
|
||||||
|
memory, Z_BUF_ERROR if there was not enough room in the output buffer,
|
||||||
|
Z_STREAM_ERROR if the level parameter is invalid.
|
||||||
|
*/
|
||||||
//go:linkname Compress2 C.compress2
|
//go:linkname Compress2 C.compress2
|
||||||
func Compress2(dest *byte, destLen *c.Ulong, source *byte, sourceLen c.Ulong, level c.Int) c.Int
|
func Compress2(dest *byte, destLen *c.Ulong, source *byte, sourceLen c.Ulong, level c.Int) c.Int
|
||||||
|
|
||||||
|
/*
|
||||||
|
ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
|
||||||
|
const Bytef *source, uLong sourceLen));
|
||||||
|
|
||||||
|
Decompresses the source buffer into the destination buffer. sourceLen is
|
||||||
|
the byte length of the source buffer. Upon entry, destLen is the total size
|
||||||
|
of the destination buffer, which must be large enough to hold the entire
|
||||||
|
uncompressed data. (The size of the uncompressed data must have been saved
|
||||||
|
previously by the compressor and transmitted to the decompressor by some
|
||||||
|
mechanism outside the scope of this compression library.) Upon exit, destLen
|
||||||
|
is the actual size of the uncompressed data.
|
||||||
|
|
||||||
|
uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
|
||||||
|
enough memory, Z_BUF_ERROR if there was not enough room in the output
|
||||||
|
buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In
|
||||||
|
the case where there is not enough room, uncompress() will fill the output
|
||||||
|
buffer with the uncompressed data up to that point.
|
||||||
|
*/
|
||||||
//go:linkname Uncompress C.uncompress
|
//go:linkname Uncompress C.uncompress
|
||||||
func Uncompress(dest *byte, destLen *c.Ulong, source *byte, sourceLen c.Ulong) c.Int
|
func Uncompress(dest *byte, destLen *c.Ulong, source *byte, sourceLen c.Ulong) c.Int
|
||||||
|
|
||||||
|
/*
|
||||||
|
ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen,
|
||||||
|
const Bytef *source, uLong *sourceLen));
|
||||||
|
|
||||||
|
Same as uncompress, except that sourceLen is a pointer, where the
|
||||||
|
length of the source is *sourceLen. On return, *sourceLen is the number of
|
||||||
|
source bytes consumed.
|
||||||
|
*/
|
||||||
//go:linkname Uncompress2 C.uncompress2
|
//go:linkname Uncompress2 C.uncompress2
|
||||||
func Uncompress2(dest *byte, destLen *c.Ulong, source *byte, sourceLen *c.Ulong) c.Int
|
func Uncompress2(dest *byte, destLen *c.Ulong, source *byte, sourceLen *c.Ulong) c.Int
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/*
|
||||||
|
ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
|
||||||
|
|
||||||
|
Update a running CRC-32 with the bytes buf[0..len-1] and return the
|
||||||
|
updated CRC-32. If buf is Z_NULL, this function returns the required
|
||||||
|
initial value for the crc. Pre- and post-conditioning (one's complement) is
|
||||||
|
performed within this function so it shouldn't be done by the application.
|
||||||
|
|
||||||
|
Usage example:
|
||||||
|
|
||||||
|
uLong crc = crc32(0L, Z_NULL, 0);
|
||||||
|
|
||||||
|
while (read_buffer(buffer, length) != EOF) {
|
||||||
|
crc = crc32(crc, buffer, length);
|
||||||
|
}
|
||||||
|
if (crc != original_crc) error();
|
||||||
|
*/
|
||||||
|
//go:linkname Crc32 C.crc32
|
||||||
|
func Crc32(crc c.Ulong, buf *byte, len c.Uint) c.Ulong
|
||||||
|
|
||||||
|
/*
|
||||||
|
ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf, z_size_t len));
|
||||||
|
|
||||||
|
Same as crc32(), but with a size_t length.
|
||||||
|
*/
|
||||||
|
//go:linkname Crc32Z C.crc32_z
|
||||||
|
func Crc32Z(crc c.Ulong, buf *byte, len uintptr) c.Ulong
|
||||||
|
|
||||||
|
func Crc32ZBytes(crc c.Ulong, buf []byte) c.Ulong {
|
||||||
|
return Crc32Z(crc, unsafe.SliceData(buf), uintptr(len(buf)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Crc32ZString(crc c.Ulong, buf string) c.Ulong {
|
||||||
|
return Crc32Z(crc, unsafe.StringData(buf), uintptr(len(buf)))
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
|
||||||
|
|
||||||
|
Combine two CRC-32 check values into one. For two sequences of bytes,
|
||||||
|
seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
|
||||||
|
calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32
|
||||||
|
check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
|
||||||
|
len2.
|
||||||
|
*/
|
||||||
|
//go:linkname Crc32Combine C.crc32_combine
|
||||||
|
func Crc32Combine(crc1 c.Ulong, crc2 c.Ulong, len2 int64) c.Ulong
|
||||||
|
|
||||||
|
/*
|
||||||
|
ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
|
||||||
|
|
||||||
|
Update a running Adler-32 checksum with the bytes buf[0..len-1] and
|
||||||
|
return the updated checksum. If buf is Z_NULL, this function returns the
|
||||||
|
required initial value for the checksum.
|
||||||
|
|
||||||
|
An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed
|
||||||
|
much faster.
|
||||||
|
|
||||||
|
Usage example:
|
||||||
|
|
||||||
|
uLong adler = adler32(0L, Z_NULL, 0);
|
||||||
|
|
||||||
|
while (read_buffer(buffer, length) != EOF) {
|
||||||
|
adler = adler32(adler, buffer, length);
|
||||||
|
}
|
||||||
|
if (adler != original_adler) error();
|
||||||
|
*/
|
||||||
|
//go:linkname Adler32 C.adler32
|
||||||
|
func Adler32(adler c.Ulong, buf *byte, len c.Uint) c.Ulong
|
||||||
|
|
||||||
|
/*
|
||||||
|
ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf, z_size_t len));
|
||||||
|
|
||||||
|
Same as adler32(), but with a size_t length.
|
||||||
|
*/
|
||||||
|
//go:linkname Adler32Z C.adler32_z
|
||||||
|
func Adler32Z(adler c.Ulong, buf *byte, len uintptr) c.Ulong
|
||||||
|
|
||||||
|
func Adler32ZBytes(adler c.Ulong, buf []byte) c.Ulong {
|
||||||
|
return Adler32Z(adler, unsafe.SliceData(buf), uintptr(len(buf)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Adler32ZString(adler c.Ulong, buf string) c.Ulong {
|
||||||
|
return Adler32Z(adler, unsafe.StringData(buf), uintptr(len(buf)))
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, z_off_t len2));
|
||||||
|
|
||||||
|
Combine two Adler-32 checksums into one. For two sequences of bytes, seq1
|
||||||
|
and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
|
||||||
|
each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of
|
||||||
|
seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note
|
||||||
|
that the z_off_t type (like off_t) is a signed integer. If len2 is
|
||||||
|
negative, the result has no meaning or utility.
|
||||||
|
*/
|
||||||
|
//go:linkname Adler32Combine C.adler32_combine
|
||||||
|
func Adler32Combine(adler1 c.Ulong, adler2 c.Ulong, len2 int64) c.Ulong
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
60
chore/_xtool/llcppsymg/config/config.go
Normal file
60
chore/_xtool/llcppsymg/config/config.go
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/cjson"
|
||||||
|
"github.com/goplus/llgo/chore/llcppg/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Conf struct {
|
||||||
|
*cjson.JSON
|
||||||
|
*types.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetConf(data []byte) (Conf, error) {
|
||||||
|
parsedConf := cjson.ParseBytes(data)
|
||||||
|
if parsedConf == nil {
|
||||||
|
return Conf{}, errors.New("failed to parse config")
|
||||||
|
}
|
||||||
|
|
||||||
|
config := &types.Config{
|
||||||
|
Name: GetStringItem(parsedConf, "name", ""),
|
||||||
|
CFlags: GetStringItem(parsedConf, "cflags", ""),
|
||||||
|
Libs: GetStringItem(parsedConf, "libs", ""),
|
||||||
|
Include: GetStringArrayItem(parsedConf, "include"),
|
||||||
|
TrimPrefixes: GetStringArrayItem(parsedConf, "trimPrefixes"),
|
||||||
|
}
|
||||||
|
|
||||||
|
return Conf{
|
||||||
|
JSON: parsedConf,
|
||||||
|
Config: config,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetString(obj *cjson.JSON) (value string) {
|
||||||
|
str := obj.GetStringValue()
|
||||||
|
return unsafe.String((*byte)(unsafe.Pointer(str)), c.Strlen(str))
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetStringItem(obj *cjson.JSON, key string, defval string) (value string) {
|
||||||
|
item := obj.GetObjectItemCaseSensitive(c.AllocaCStr(key))
|
||||||
|
if item == nil {
|
||||||
|
return defval
|
||||||
|
}
|
||||||
|
return GetString(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetStringArrayItem(obj *cjson.JSON, key string) (value []string) {
|
||||||
|
item := obj.GetObjectItemCaseSensitive(c.AllocaCStr(key))
|
||||||
|
if item == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
value = make([]string, item.GetArraySize())
|
||||||
|
for i := range value {
|
||||||
|
value[i] = GetString(item.GetArrayItem(c.Int(i)))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -17,12 +17,22 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"github.com/goplus/llgo/c"
|
"github.com/goplus/llgo/c"
|
||||||
"github.com/goplus/llgo/c/cjson"
|
"github.com/goplus/llgo/c/cjson"
|
||||||
|
"github.com/goplus/llgo/chore/_xtool/llcppsymg/config"
|
||||||
|
"github.com/goplus/llgo/chore/_xtool/llcppsymg/parse"
|
||||||
|
"github.com/goplus/llgo/chore/llcppg/types"
|
||||||
|
"github.com/goplus/llgo/cpp/llvm"
|
||||||
|
"github.com/goplus/llgo/xtool/nm"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -40,14 +50,25 @@ func main() {
|
|||||||
}
|
}
|
||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
conf := cjson.ParseBytes(data)
|
conf, err := config.GetConf(data)
|
||||||
if conf == nil {
|
check(err)
|
||||||
fmt.Fprintln(os.Stderr, "Failed to parse config file:", cfgFile)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
defer conf.Delete()
|
defer conf.Delete()
|
||||||
|
|
||||||
c.Printf(c.Str("%s"), conf.Print())
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, "Failed to parse config file:", cfgFile)
|
||||||
|
}
|
||||||
|
symbols, err := parseDylibSymbols(conf.Libs)
|
||||||
|
|
||||||
|
check(err)
|
||||||
|
|
||||||
|
filepaths := generateHeaderFilePath(conf.CFlags, conf.Include)
|
||||||
|
astInfos, err := parse.ParseHeaderFile(filepaths)
|
||||||
|
check(err)
|
||||||
|
|
||||||
|
symbolInfo := getCommonSymbols(symbols, astInfos, conf.TrimPrefixes)
|
||||||
|
|
||||||
|
err = genSymbolTableFile(symbolInfo)
|
||||||
|
check(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func check(err error) {
|
func check(err error) {
|
||||||
@@ -55,3 +76,230 @@ func check(err error) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseDylibSymbols(lib string) ([]types.CPPSymbol, error) {
|
||||||
|
dylibPath, err := generateDylibPath(lib)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("failed to generate dylib path")
|
||||||
|
}
|
||||||
|
|
||||||
|
files, err := nm.New("").List(dylibPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("failed to list symbols in dylib")
|
||||||
|
}
|
||||||
|
|
||||||
|
var symbols []types.CPPSymbol
|
||||||
|
|
||||||
|
for _, file := range files {
|
||||||
|
for _, sym := range file.Symbols {
|
||||||
|
demangleName := decodeSymbolName(sym.Name)
|
||||||
|
symbols = append(symbols, types.CPPSymbol{
|
||||||
|
Symbol: sym,
|
||||||
|
DemangleName: demangleName,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return symbols, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateDylibPath(lib string) (string, error) {
|
||||||
|
output := lib
|
||||||
|
libPath := ""
|
||||||
|
libName := ""
|
||||||
|
for _, part := range strings.Fields(string(output)) {
|
||||||
|
if strings.HasPrefix(part, "-L") {
|
||||||
|
libPath = part[2:]
|
||||||
|
} else if strings.HasPrefix(part, "-l") {
|
||||||
|
libName = part[2:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if libPath == "" || libName == "" {
|
||||||
|
return "", fmt.Errorf("failed to parse pkg-config output: %s", output)
|
||||||
|
}
|
||||||
|
|
||||||
|
dylibPath := filepath.Join(libPath, "lib"+libName+".dylib")
|
||||||
|
return dylibPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodeSymbolName(symbolName string) string {
|
||||||
|
if symbolName == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
demangled := llvm.ItaniumDemangle(symbolName, true)
|
||||||
|
if demangled == nil {
|
||||||
|
return symbolName
|
||||||
|
}
|
||||||
|
defer c.Free(unsafe.Pointer(demangled))
|
||||||
|
|
||||||
|
demangleName := c.GoString(demangled)
|
||||||
|
if demangleName == "" {
|
||||||
|
return symbolName
|
||||||
|
}
|
||||||
|
|
||||||
|
decodedName := strings.TrimSpace(demangleName)
|
||||||
|
decodedName = strings.ReplaceAll(decodedName,
|
||||||
|
"std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const",
|
||||||
|
"std::string")
|
||||||
|
|
||||||
|
return decodedName
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateHeaderFilePath(cflags string, files []string) []string {
|
||||||
|
prefixPath := cflags
|
||||||
|
prefixPath = strings.TrimPrefix(prefixPath, "-I")
|
||||||
|
var includePaths []string
|
||||||
|
for _, file := range files {
|
||||||
|
includePaths = append(includePaths, filepath.Join(prefixPath, "/"+file))
|
||||||
|
}
|
||||||
|
return includePaths
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCommonSymbols(dylibSymbols []types.CPPSymbol, astInfoList []types.ASTInformation, prefix []string) []types.SymbolInfo {
|
||||||
|
var commonSymbols []types.SymbolInfo
|
||||||
|
functionNameMap := make(map[string]int)
|
||||||
|
|
||||||
|
for _, astInfo := range astInfoList {
|
||||||
|
for _, dylibSym := range dylibSymbols {
|
||||||
|
if strings.TrimPrefix(dylibSym.Name, "_") == astInfo.Symbol {
|
||||||
|
cppName := generateCPPName(astInfo)
|
||||||
|
functionNameMap[cppName]++
|
||||||
|
symbolInfo := types.SymbolInfo{
|
||||||
|
Mangle: strings.TrimPrefix(dylibSym.Name, "_"),
|
||||||
|
CPP: cppName,
|
||||||
|
Go: generateMangle(astInfo, functionNameMap[cppName], prefix),
|
||||||
|
}
|
||||||
|
commonSymbols = append(commonSymbols, symbolInfo)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return commonSymbols
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateCPPName(astInfo types.ASTInformation) string {
|
||||||
|
cppName := astInfo.Name
|
||||||
|
if astInfo.Class != "" {
|
||||||
|
cppName = astInfo.Class + "::" + astInfo.Name
|
||||||
|
}
|
||||||
|
return cppName
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateMangle(astInfo types.ASTInformation, count int, prefixes []string) string {
|
||||||
|
astInfo.Class = removePrefix(astInfo.Class, prefixes)
|
||||||
|
astInfo.Name = removePrefix(astInfo.Name, prefixes)
|
||||||
|
res := ""
|
||||||
|
if astInfo.Class != "" {
|
||||||
|
if astInfo.Class == astInfo.Name {
|
||||||
|
res = "(*" + astInfo.Class + ")." + "Init"
|
||||||
|
if count > 1 {
|
||||||
|
res += "__" + strconv.Itoa(count-1)
|
||||||
|
}
|
||||||
|
} else if astInfo.Name == "~"+astInfo.Class {
|
||||||
|
res = "(*" + astInfo.Class + ")." + "Dispose"
|
||||||
|
if count > 1 {
|
||||||
|
res += "__" + strconv.Itoa(count-1)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res = "(*" + astInfo.Class + ")." + astInfo.Name
|
||||||
|
if count > 1 {
|
||||||
|
res += "__" + strconv.Itoa(count-1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res = astInfo.Name
|
||||||
|
if count > 1 {
|
||||||
|
res += "__" + strconv.Itoa(count-1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func removePrefix(str string, prefixes []string) string {
|
||||||
|
for _, prefix := range prefixes {
|
||||||
|
if strings.HasPrefix(str, prefix) {
|
||||||
|
return strings.TrimPrefix(str, prefix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
func genSymbolTableFile(symbolInfos []types.SymbolInfo) error {
|
||||||
|
// keep open follow code block can run successfully
|
||||||
|
for i := range symbolInfos {
|
||||||
|
println("symbol", symbolInfos[i].Go)
|
||||||
|
}
|
||||||
|
|
||||||
|
fileName := "llcppg.symb.json"
|
||||||
|
existingSymbols, err := readExistingSymbolTable(fileName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range symbolInfos {
|
||||||
|
if existingSymbol, exists := existingSymbols[symbolInfos[i].Mangle]; exists {
|
||||||
|
symbolInfos[i].Go = existingSymbol.Go
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
root := cjson.Array()
|
||||||
|
defer root.Delete()
|
||||||
|
|
||||||
|
for _, symbol := range symbolInfos {
|
||||||
|
item := cjson.Object()
|
||||||
|
item.SetItem(c.Str("mangle"), cjson.String(c.AllocaCStr(symbol.Mangle)))
|
||||||
|
item.SetItem(c.Str("c++"), cjson.String(c.AllocaCStr(symbol.CPP)))
|
||||||
|
item.SetItem(c.Str("go"), cjson.String(c.AllocaCStr(symbol.Go)))
|
||||||
|
root.AddItem(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
cStr := root.Print()
|
||||||
|
if cStr == nil {
|
||||||
|
return errors.New("symbol table is empty")
|
||||||
|
}
|
||||||
|
defer c.Free(unsafe.Pointer(cStr))
|
||||||
|
|
||||||
|
data := unsafe.Slice((*byte)(unsafe.Pointer(cStr)), c.Strlen(cStr))
|
||||||
|
|
||||||
|
if err := os.WriteFile(fileName, data, 0644); err != nil {
|
||||||
|
return errors.New("failed to write symbol table file")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func readExistingSymbolTable(fileName string) (map[string]types.SymbolInfo, error) {
|
||||||
|
existingSymbols := make(map[string]types.SymbolInfo)
|
||||||
|
|
||||||
|
if _, err := os.Stat(fileName); err != nil {
|
||||||
|
return existingSymbols, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := os.ReadFile(fileName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("failed to read symbol table file")
|
||||||
|
}
|
||||||
|
|
||||||
|
parsedJSON := cjson.ParseBytes(data)
|
||||||
|
if parsedJSON == nil {
|
||||||
|
return nil, errors.New("failed to parse JSON")
|
||||||
|
}
|
||||||
|
|
||||||
|
arraySize := parsedJSON.GetArraySize()
|
||||||
|
|
||||||
|
for i := 0; i < int(arraySize); i++ {
|
||||||
|
item := parsedJSON.GetArrayItem(c.Int(i))
|
||||||
|
if item == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
symbol := types.SymbolInfo{
|
||||||
|
Mangle: config.GetStringItem(item, "mangle", ""),
|
||||||
|
CPP: config.GetStringItem(item, "c++", ""),
|
||||||
|
Go: config.GetStringItem(item, "go", ""),
|
||||||
|
}
|
||||||
|
existingSymbols[symbol.Mangle] = symbol
|
||||||
|
}
|
||||||
|
|
||||||
|
return existingSymbols, nil
|
||||||
|
}
|
||||||
|
|||||||
153
chore/_xtool/llcppsymg/parse/parse.go
Normal file
153
chore/_xtool/llcppsymg/parse/parse.go
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
package parse
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"strconv"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/clang"
|
||||||
|
"github.com/goplus/llgo/chore/llcppg/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Context struct {
|
||||||
|
namespaceName string
|
||||||
|
className string
|
||||||
|
astInfo []types.ASTInformation
|
||||||
|
currentFile string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newContext() *Context {
|
||||||
|
return &Context{
|
||||||
|
astInfo: make([]types.ASTInformation, 0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Context) setNamespaceName(name string) {
|
||||||
|
c.namespaceName = name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Context) setClassName(name string) {
|
||||||
|
c.className = name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Context) setCurrentFile(filename string) {
|
||||||
|
c.currentFile = filename
|
||||||
|
}
|
||||||
|
|
||||||
|
var context = newContext()
|
||||||
|
|
||||||
|
func collectFuncInfo(cursor clang.Cursor) types.ASTInformation {
|
||||||
|
|
||||||
|
info := types.ASTInformation{
|
||||||
|
Namespace: context.namespaceName,
|
||||||
|
Class: context.className,
|
||||||
|
}
|
||||||
|
|
||||||
|
cursorStr := cursor.String()
|
||||||
|
symbol := cursor.Mangling()
|
||||||
|
|
||||||
|
info.Name = c.GoString(cursorStr.CStr())
|
||||||
|
|
||||||
|
info.Symbol = c.GoString(symbol.CStr())
|
||||||
|
if len(info.Symbol) >= 1 {
|
||||||
|
if info.Symbol[0] == '_' {
|
||||||
|
info.Symbol = info.Symbol[1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defer symbol.Dispose()
|
||||||
|
defer cursorStr.Dispose()
|
||||||
|
|
||||||
|
if context.namespaceName != "" {
|
||||||
|
info.Namespace = context.namespaceName
|
||||||
|
}
|
||||||
|
if context.className != "" {
|
||||||
|
info.Class = context.className
|
||||||
|
}
|
||||||
|
|
||||||
|
typeStr := cursor.ResultType().String()
|
||||||
|
defer typeStr.Dispose()
|
||||||
|
info.ReturnType = c.GoString(typeStr.CStr())
|
||||||
|
|
||||||
|
info.Parameters = make([]types.Parameter, cursor.NumArguments())
|
||||||
|
for i := 0; i < int(cursor.NumArguments()); i++ {
|
||||||
|
argCurSor := cursor.Argument(c.Uint(i))
|
||||||
|
argType := argCurSor.Type().String()
|
||||||
|
argName := argCurSor.String()
|
||||||
|
info.Parameters[i] = types.Parameter{
|
||||||
|
Name: c.GoString(argName.CStr()),
|
||||||
|
Type: c.GoString(argType.CStr()),
|
||||||
|
}
|
||||||
|
|
||||||
|
argType.Dispose()
|
||||||
|
argName.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
|
func visit(cursor, parent clang.Cursor, clientData c.Pointer) clang.ChildVisitResult {
|
||||||
|
if cursor.Kind == clang.Namespace {
|
||||||
|
nameStr := cursor.String()
|
||||||
|
context.setNamespaceName(c.GoString(nameStr.CStr()))
|
||||||
|
clang.VisitChildren(cursor, visit, nil)
|
||||||
|
context.setNamespaceName("")
|
||||||
|
} else if cursor.Kind == clang.ClassDecl {
|
||||||
|
nameStr := cursor.String()
|
||||||
|
context.setClassName(c.GoString(nameStr.CStr()))
|
||||||
|
clang.VisitChildren(cursor, visit, nil)
|
||||||
|
context.setClassName("")
|
||||||
|
} else if cursor.Kind == clang.CXXMethod || cursor.Kind == clang.FunctionDecl || cursor.Kind == clang.Constructor || cursor.Kind == clang.Destructor {
|
||||||
|
loc := cursor.Location()
|
||||||
|
var file clang.File
|
||||||
|
var line, column c.Uint
|
||||||
|
|
||||||
|
loc.SpellingLocation(&file, &line, &column, nil)
|
||||||
|
filename := file.FileName()
|
||||||
|
|
||||||
|
if c.Strcmp(filename.CStr(), c.AllocaCStr(context.currentFile)) == 0 {
|
||||||
|
info := collectFuncInfo(cursor)
|
||||||
|
info.Location = c.GoString(filename.CStr()) + ":" + strconv.Itoa(int(line)) + ":" + strconv.Itoa(int(column))
|
||||||
|
context.astInfo = append(context.astInfo, info)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer filename.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
return clang.ChildVisit_Continue
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseHeaderFile(filepaths []string) ([]types.ASTInformation, error) {
|
||||||
|
|
||||||
|
index := clang.CreateIndex(0, 0)
|
||||||
|
args := make([]*c.Char, 3)
|
||||||
|
args[0] = c.Str("-x")
|
||||||
|
args[1] = c.Str("c++")
|
||||||
|
args[2] = c.Str("-std=c++11")
|
||||||
|
context = newContext()
|
||||||
|
|
||||||
|
for _, filename := range filepaths {
|
||||||
|
unit := index.ParseTranslationUnit(
|
||||||
|
c.AllocaCStr(filename),
|
||||||
|
unsafe.SliceData(args), 3,
|
||||||
|
nil, 0,
|
||||||
|
clang.TranslationUnit_None,
|
||||||
|
)
|
||||||
|
|
||||||
|
if unit == nil {
|
||||||
|
return nil, errors.New("Unable to parse translation unit for file " + filename)
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor := unit.Cursor()
|
||||||
|
context.setCurrentFile(filename)
|
||||||
|
|
||||||
|
clang.VisitChildren(cursor, visit, nil)
|
||||||
|
|
||||||
|
unit.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
index.Dispose()
|
||||||
|
|
||||||
|
return context.astInfo, nil
|
||||||
|
}
|
||||||
@@ -16,6 +16,10 @@
|
|||||||
|
|
||||||
package types
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/xtool/nm"
|
||||||
|
)
|
||||||
|
|
||||||
// Config represents a configuration for the llcppg tool.
|
// Config represents a configuration for the llcppg tool.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
@@ -24,3 +28,30 @@ type Config struct {
|
|||||||
Include []string `json:"include"`
|
Include []string `json:"include"`
|
||||||
TrimPrefixes []string `json:"trimPrefixes"`
|
TrimPrefixes []string `json:"trimPrefixes"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CPPSymbol struct {
|
||||||
|
DemangleName string
|
||||||
|
*nm.Symbol
|
||||||
|
}
|
||||||
|
|
||||||
|
type ASTInformation struct {
|
||||||
|
Namespace string `json:"namespace"`
|
||||||
|
Class string `json:"class"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
BaseClasses []string `json:"baseClasses"`
|
||||||
|
ReturnType string `json:"returnType"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
Parameters []Parameter `json:"parameters"`
|
||||||
|
Symbol string `json:"symbol"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Parameter struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SymbolInfo struct {
|
||||||
|
Mangle string `json:"mangle"` // C++ Symbol
|
||||||
|
CPP string `json:"c++"` // C++ function name
|
||||||
|
Go string `json:"go"` // Go function name
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/goplus/llgo/xtool/env/llvm"
|
"github.com/goplus/llgo/xtool/env/llvm"
|
||||||
"github.com/goplus/llgo/xtool/nm"
|
"github.com/goplus/llgo/xtool/nm/nmindex"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -58,7 +58,7 @@ func makeIndex() {
|
|||||||
idxDir := indexDir()
|
idxDir := indexDir()
|
||||||
os.MkdirAll(idxDir, 0755)
|
os.MkdirAll(idxDir, 0755)
|
||||||
|
|
||||||
b := nm.NewIndexBuilder(env.Nm())
|
b := nmindex.NewIndexBuilder(env.Nm())
|
||||||
libDirs := []string{
|
libDirs := []string{
|
||||||
usrLib(false),
|
usrLib(false),
|
||||||
usrLib(true),
|
usrLib(true),
|
||||||
@@ -78,7 +78,7 @@ func query(q string) {
|
|||||||
q = "_" + q
|
q = "_" + q
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
files, err := nm.Query(indexDir(), q)
|
files, err := nmindex.Query(indexDir(), q)
|
||||||
check(err)
|
check(err)
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
fmt.Printf("%s:\n", f.ArFile)
|
fmt.Printf("%s:\n", f.ArFile)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
source_filename = "main"
|
source_filename = "main"
|
||||||
|
|
||||||
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
|
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
|
||||||
|
%main.T = type { ptr, ptr }
|
||||||
|
|
||||||
@"main.init$guard" = global i1 false, align 1
|
@"main.init$guard" = global i1 false, align 1
|
||||||
@__llgo_argc = global i32 0, align 4
|
@__llgo_argc = global i32 0, align 4
|
||||||
@@ -37,12 +38,12 @@ _llgo_0:
|
|||||||
store i64 3, ptr %5, align 4
|
store i64 3, ptr %5, align 4
|
||||||
%6 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %3, align 8
|
%6 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %3, align 8
|
||||||
store %"github.com/goplus/llgo/internal/runtime.String" %6, ptr %2, align 8
|
store %"github.com/goplus/llgo/internal/runtime.String" %6, ptr %2, align 8
|
||||||
%7 = alloca { ptr, ptr }, align 8
|
%7 = alloca %main.T, align 8
|
||||||
%8 = getelementptr inbounds { ptr, ptr }, ptr %7, i32 0, i32 0
|
%8 = getelementptr inbounds %main.T, ptr %7, i32 0, i32 0
|
||||||
store ptr @"__llgo_stub.main.main$1", ptr %8, align 8
|
store ptr @"__llgo_stub.main.main$1", ptr %8, align 8
|
||||||
%9 = getelementptr inbounds { ptr, ptr }, ptr %7, i32 0, i32 1
|
%9 = getelementptr inbounds %main.T, ptr %7, i32 0, i32 1
|
||||||
store ptr null, ptr %9, align 8
|
store ptr null, ptr %9, align 8
|
||||||
%10 = load { ptr, ptr }, ptr %7, align 8
|
%10 = load %main.T, ptr %7, align 8
|
||||||
%11 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8)
|
%11 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8)
|
||||||
%12 = getelementptr inbounds { ptr }, ptr %11, i32 0, i32 0
|
%12 = getelementptr inbounds { ptr }, ptr %11, i32 0, i32 0
|
||||||
store ptr %2, ptr %12, align 8
|
store ptr %2, ptr %12, align 8
|
||||||
@@ -52,12 +53,15 @@ _llgo_0:
|
|||||||
%15 = getelementptr inbounds { ptr, ptr }, ptr %13, i32 0, i32 1
|
%15 = getelementptr inbounds { ptr, ptr }, ptr %13, i32 0, i32 1
|
||||||
store ptr %11, ptr %15, align 8
|
store ptr %11, ptr %15, align 8
|
||||||
%16 = load { ptr, ptr }, ptr %13, align 8
|
%16 = load { ptr, ptr }, ptr %13, align 8
|
||||||
%17 = extractvalue { ptr, ptr } %10, 1
|
%17 = alloca %main.T, align 8
|
||||||
%18 = extractvalue { ptr, ptr } %10, 0
|
store { ptr, ptr } %16, ptr %17, align 8
|
||||||
call void %18(ptr %17, i64 100)
|
%18 = load %main.T, ptr %17, align 8
|
||||||
%19 = extractvalue { ptr, ptr } %16, 1
|
%19 = extractvalue %main.T %10, 1
|
||||||
%20 = extractvalue { ptr, ptr } %16, 0
|
%20 = extractvalue %main.T %10, 0
|
||||||
call void %20(ptr %19, i64 200)
|
call void %20(ptr %19, i64 100)
|
||||||
|
%21 = extractvalue %main.T %18, 1
|
||||||
|
%22 = extractvalue %main.T %18, 0
|
||||||
|
call void %22(ptr %21, i64 200)
|
||||||
ret i32 0
|
ret i32 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
17
cl/_testgo/defer5/in.go
Normal file
17
cl/_testgo/defer5/in.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
defer println("A")
|
||||||
|
defer func() {
|
||||||
|
if e := recover(); e != nil {
|
||||||
|
println("in defer 1")
|
||||||
|
panic("panic in defer 1")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
defer func() {
|
||||||
|
println("in defer 2")
|
||||||
|
panic("panic in defer 2")
|
||||||
|
}()
|
||||||
|
defer println("B")
|
||||||
|
panic("panic in main")
|
||||||
|
}
|
||||||
1
cl/_testgo/defer5/out.ll
Normal file
1
cl/_testgo/defer5/out.ll
Normal file
@@ -0,0 +1 @@
|
|||||||
|
;
|
||||||
@@ -304,13 +304,13 @@ _llgo_0:
|
|||||||
%14 = getelementptr inbounds %main.T5, ptr %13, i32 0, i32 0
|
%14 = getelementptr inbounds %main.T5, ptr %13, i32 0, i32 0
|
||||||
store i64 300, ptr %14, align 4
|
store i64 300, ptr %14, align 4
|
||||||
%15 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 16)
|
%15 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 16)
|
||||||
%16 = alloca { ptr, ptr }, align 8
|
%16 = alloca %main.T6, align 8
|
||||||
%17 = getelementptr inbounds { ptr, ptr }, ptr %16, i32 0, i32 0
|
%17 = getelementptr inbounds %main.T6, ptr %16, i32 0, i32 0
|
||||||
store ptr @"__llgo_stub.main.main$1", ptr %17, align 8
|
store ptr @"__llgo_stub.main.main$1", ptr %17, align 8
|
||||||
%18 = getelementptr inbounds { ptr, ptr }, ptr %16, i32 0, i32 1
|
%18 = getelementptr inbounds %main.T6, ptr %16, i32 0, i32 1
|
||||||
store ptr null, ptr %18, align 8
|
store ptr null, ptr %18, align 8
|
||||||
%19 = load { ptr, ptr }, ptr %16, align 8
|
%19 = load %main.T6, ptr %16, align 8
|
||||||
store { ptr, ptr } %19, ptr %15, align 8
|
store %main.T6 %19, ptr %15, align 8
|
||||||
%20 = load %main.T, ptr %2, align 8
|
%20 = load %main.T, ptr %2, align 8
|
||||||
%21 = load ptr, ptr @_llgo_main.T, align 8
|
%21 = load ptr, ptr @_llgo_main.T, align 8
|
||||||
%22 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 16)
|
%22 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 16)
|
||||||
|
|||||||
63
cl/_testrt/closureconv/in.go
Normal file
63
cl/_testrt/closureconv/in.go
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type Func func(a int, b int) int
|
||||||
|
type Func2 func(a int, b int) int
|
||||||
|
|
||||||
|
type Call struct {
|
||||||
|
fn Func
|
||||||
|
n int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Call) add(a int, b int) int {
|
||||||
|
return a + b + c.n
|
||||||
|
}
|
||||||
|
|
||||||
|
func add(a int, b int) int {
|
||||||
|
return a + b
|
||||||
|
}
|
||||||
|
|
||||||
|
func demo1(n int) Func {
|
||||||
|
m := &Call{n: n}
|
||||||
|
m.fn = m.add
|
||||||
|
return m.fn
|
||||||
|
}
|
||||||
|
|
||||||
|
func demo2() Func {
|
||||||
|
m := &Call{}
|
||||||
|
return m.add
|
||||||
|
}
|
||||||
|
|
||||||
|
func demo3() Func {
|
||||||
|
return add
|
||||||
|
}
|
||||||
|
|
||||||
|
func demo4() Func {
|
||||||
|
return func(a, b int) int { return a + b }
|
||||||
|
}
|
||||||
|
|
||||||
|
func demo5(n int) Func {
|
||||||
|
return func(a, b int) int { return a + b + n }
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
n1 := demo1(1)(99, 200)
|
||||||
|
println(n1)
|
||||||
|
|
||||||
|
n2 := demo2()(100, 200)
|
||||||
|
println(n2)
|
||||||
|
|
||||||
|
n3 := demo3()(100, 200)
|
||||||
|
println(n3)
|
||||||
|
|
||||||
|
n4 := demo4()(100, 200)
|
||||||
|
println(n4)
|
||||||
|
|
||||||
|
n5 := demo5(1)(99, 200)
|
||||||
|
println(n5)
|
||||||
|
|
||||||
|
var fn func(a int, b int) int = demo5(1)
|
||||||
|
println(fn(99, 200))
|
||||||
|
|
||||||
|
var fn2 Func2 = (Func2)(demo5(1))
|
||||||
|
println(fn2(99, 200))
|
||||||
|
}
|
||||||
220
cl/_testrt/closureconv/out.ll
Normal file
220
cl/_testrt/closureconv/out.ll
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
%main.Call = type { %main.Func, i64 }
|
||||||
|
%main.Func = type { ptr, ptr }
|
||||||
|
|
||||||
|
@"main.init$guard" = global i1 false, align 1
|
||||||
|
@__llgo_argc = global i32 0, align 4
|
||||||
|
@__llgo_argv = global ptr null, align 8
|
||||||
|
|
||||||
|
define i64 @"main.(*Call).add"(ptr %0, i64 %1, i64 %2) {
|
||||||
|
_llgo_0:
|
||||||
|
%3 = add i64 %1, %2
|
||||||
|
%4 = getelementptr inbounds %main.Call, ptr %0, i32 0, i32 1
|
||||||
|
%5 = load i64, ptr %4, align 4
|
||||||
|
%6 = add i64 %3, %5
|
||||||
|
ret i64 %6
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @main.add(i64 %0, i64 %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = add i64 %0, %1
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define %main.Func @main.demo1(i64 %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 24)
|
||||||
|
%2 = getelementptr inbounds %main.Call, ptr %1, i32 0, i32 1
|
||||||
|
store i64 %0, ptr %2, align 4
|
||||||
|
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8)
|
||||||
|
%4 = getelementptr inbounds { ptr }, ptr %3, i32 0, i32 0
|
||||||
|
store ptr %1, ptr %4, align 8
|
||||||
|
%5 = alloca { ptr, ptr }, align 8
|
||||||
|
%6 = getelementptr inbounds { ptr, ptr }, ptr %5, i32 0, i32 0
|
||||||
|
store ptr @"main.add$bound", ptr %6, align 8
|
||||||
|
%7 = getelementptr inbounds { ptr, ptr }, ptr %5, i32 0, i32 1
|
||||||
|
store ptr %3, ptr %7, align 8
|
||||||
|
%8 = load { ptr, ptr }, ptr %5, align 8
|
||||||
|
%9 = getelementptr inbounds %main.Call, ptr %1, i32 0, i32 0
|
||||||
|
%10 = alloca %main.Func, align 8
|
||||||
|
store { ptr, ptr } %8, ptr %10, align 8
|
||||||
|
%11 = load %main.Func, ptr %10, align 8
|
||||||
|
store %main.Func %11, ptr %9, align 8
|
||||||
|
%12 = getelementptr inbounds %main.Call, ptr %1, i32 0, i32 0
|
||||||
|
%13 = load %main.Func, ptr %12, align 8
|
||||||
|
ret %main.Func %13
|
||||||
|
}
|
||||||
|
|
||||||
|
define %main.Func @main.demo2() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 24)
|
||||||
|
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8)
|
||||||
|
%2 = getelementptr inbounds { ptr }, ptr %1, i32 0, i32 0
|
||||||
|
store ptr %0, ptr %2, align 8
|
||||||
|
%3 = alloca { ptr, ptr }, align 8
|
||||||
|
%4 = getelementptr inbounds { ptr, ptr }, ptr %3, i32 0, i32 0
|
||||||
|
store ptr @"main.add$bound", ptr %4, align 8
|
||||||
|
%5 = getelementptr inbounds { ptr, ptr }, ptr %3, i32 0, i32 1
|
||||||
|
store ptr %1, ptr %5, align 8
|
||||||
|
%6 = load { ptr, ptr }, ptr %3, align 8
|
||||||
|
%7 = alloca %main.Func, align 8
|
||||||
|
store { ptr, ptr } %6, ptr %7, align 8
|
||||||
|
%8 = load %main.Func, ptr %7, align 8
|
||||||
|
ret %main.Func %8
|
||||||
|
}
|
||||||
|
|
||||||
|
define %main.Func @main.demo3() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = alloca %main.Func, align 8
|
||||||
|
%1 = getelementptr inbounds %main.Func, ptr %0, i32 0, i32 0
|
||||||
|
store ptr @__llgo_stub.main.add, ptr %1, align 8
|
||||||
|
%2 = getelementptr inbounds %main.Func, ptr %0, i32 0, i32 1
|
||||||
|
store ptr null, ptr %2, align 8
|
||||||
|
%3 = load %main.Func, ptr %0, align 8
|
||||||
|
ret %main.Func %3
|
||||||
|
}
|
||||||
|
|
||||||
|
define %main.Func @main.demo4() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = alloca %main.Func, align 8
|
||||||
|
%1 = getelementptr inbounds %main.Func, ptr %0, i32 0, i32 0
|
||||||
|
store ptr @"__llgo_stub.main.demo4$1", ptr %1, align 8
|
||||||
|
%2 = getelementptr inbounds %main.Func, ptr %0, i32 0, i32 1
|
||||||
|
store ptr null, ptr %2, align 8
|
||||||
|
%3 = load %main.Func, ptr %0, align 8
|
||||||
|
ret %main.Func %3
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"main.demo4$1"(i64 %0, i64 %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = add i64 %0, %1
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define %main.Func @main.demo5(i64 %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 8)
|
||||||
|
store i64 %0, ptr %1, align 4
|
||||||
|
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8)
|
||||||
|
%3 = getelementptr inbounds { ptr }, ptr %2, i32 0, i32 0
|
||||||
|
store ptr %1, ptr %3, align 8
|
||||||
|
%4 = alloca { ptr, ptr }, align 8
|
||||||
|
%5 = getelementptr inbounds { ptr, ptr }, ptr %4, i32 0, i32 0
|
||||||
|
store ptr @"main.demo5$1", ptr %5, align 8
|
||||||
|
%6 = getelementptr inbounds { ptr, ptr }, ptr %4, i32 0, i32 1
|
||||||
|
store ptr %2, ptr %6, align 8
|
||||||
|
%7 = load { ptr, ptr }, ptr %4, align 8
|
||||||
|
%8 = alloca %main.Func, align 8
|
||||||
|
store { ptr, ptr } %7, ptr %8, align 8
|
||||||
|
%9 = load %main.Func, ptr %8, align 8
|
||||||
|
ret %main.Func %9
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"main.demo5$1"(ptr %0, i64 %1, i64 %2) {
|
||||||
|
_llgo_0:
|
||||||
|
%3 = add i64 %1, %2
|
||||||
|
%4 = load { ptr }, ptr %0, align 8
|
||||||
|
%5 = extractvalue { ptr } %4, 0
|
||||||
|
%6 = load i64, ptr %5, align 4
|
||||||
|
%7 = add i64 %3, %6
|
||||||
|
ret i64 %7
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @main(i32 %0, ptr %1) {
|
||||||
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%2 = call %main.Func @main.demo1(i64 1)
|
||||||
|
%3 = extractvalue %main.Func %2, 1
|
||||||
|
%4 = extractvalue %main.Func %2, 0
|
||||||
|
%5 = call i64 %4(ptr %3, i64 99, i64 200)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %5)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10)
|
||||||
|
%6 = call %main.Func @main.demo2()
|
||||||
|
%7 = extractvalue %main.Func %6, 1
|
||||||
|
%8 = extractvalue %main.Func %6, 0
|
||||||
|
%9 = call i64 %8(ptr %7, i64 100, i64 200)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %9)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10)
|
||||||
|
%10 = call %main.Func @main.demo3()
|
||||||
|
%11 = extractvalue %main.Func %10, 1
|
||||||
|
%12 = extractvalue %main.Func %10, 0
|
||||||
|
%13 = call i64 %12(ptr %11, i64 100, i64 200)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %13)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10)
|
||||||
|
%14 = call %main.Func @main.demo4()
|
||||||
|
%15 = extractvalue %main.Func %14, 1
|
||||||
|
%16 = extractvalue %main.Func %14, 0
|
||||||
|
%17 = call i64 %16(ptr %15, i64 100, i64 200)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %17)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10)
|
||||||
|
%18 = call %main.Func @main.demo5(i64 1)
|
||||||
|
%19 = extractvalue %main.Func %18, 1
|
||||||
|
%20 = extractvalue %main.Func %18, 0
|
||||||
|
%21 = call i64 %20(ptr %19, i64 99, i64 200)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %21)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10)
|
||||||
|
%22 = call %main.Func @main.demo5(i64 1)
|
||||||
|
%23 = alloca { ptr, ptr }, align 8
|
||||||
|
store %main.Func %22, ptr %23, align 8
|
||||||
|
%24 = load { ptr, ptr }, ptr %23, align 8
|
||||||
|
%25 = extractvalue { ptr, ptr } %24, 1
|
||||||
|
%26 = extractvalue { ptr, ptr } %24, 0
|
||||||
|
%27 = call i64 %26(ptr %25, i64 99, i64 200)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %27)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10)
|
||||||
|
%28 = call %main.Func @main.demo5(i64 1)
|
||||||
|
%29 = extractvalue %main.Func %28, 1
|
||||||
|
%30 = extractvalue %main.Func %28, 0
|
||||||
|
%31 = call i64 %30(ptr %29, i64 99, i64 200)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %31)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10)
|
||||||
|
ret i32 0
|
||||||
|
}
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
|
||||||
|
|
||||||
|
define i64 @"main.add$bound"(ptr %0, i64 %1, i64 %2) {
|
||||||
|
_llgo_0:
|
||||||
|
%3 = load { ptr }, ptr %0, align 8
|
||||||
|
%4 = extractvalue { ptr } %3, 0
|
||||||
|
%5 = call i64 @"main.(*Call).add"(ptr %4, i64 %1, i64 %2)
|
||||||
|
ret i64 %5
|
||||||
|
}
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64)
|
||||||
|
|
||||||
|
define linkonce i64 @__llgo_stub.main.add(ptr %0, i64 %1, i64 %2) {
|
||||||
|
_llgo_0:
|
||||||
|
%3 = tail call i64 @main.add(i64 %1, i64 %2)
|
||||||
|
ret i64 %3
|
||||||
|
}
|
||||||
|
|
||||||
|
define linkonce i64 @"__llgo_stub.main.demo4$1"(ptr %0, i64 %1, i64 %2) {
|
||||||
|
_llgo_0:
|
||||||
|
%3 = tail call i64 @"main.demo4$1"(i64 %1, i64 %2)
|
||||||
|
ret i64 %3
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64)
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8)
|
||||||
@@ -195,6 +195,9 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun
|
|||||||
isInit := (f.Name() == "init" && sig.Recv() == nil)
|
isInit := (f.Name() == "init" && sig.Recv() == nil)
|
||||||
if isInit && state == pkgHasPatch {
|
if isInit && state == pkgHasPatch {
|
||||||
name = initFnNameOfHasPatch(name)
|
name = initFnNameOfHasPatch(name)
|
||||||
|
// TODO(xsw): pkg.init$guard has been set, change ssa.If to ssa.Jump
|
||||||
|
block := f.Blocks[0].Instrs[1].(*ssa.If).Block()
|
||||||
|
block.Succs[0], block.Succs[1] = block.Succs[1], block.Succs[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn := pkg.FuncOf(name)
|
fn := pkg.FuncOf(name)
|
||||||
@@ -286,7 +289,7 @@ func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, do
|
|||||||
if pyModInit = p.pyMod != ""; pyModInit {
|
if pyModInit = p.pyMod != ""; pyModInit {
|
||||||
last = len(instrs) - 1
|
last = len(instrs) - 1
|
||||||
instrs = instrs[:last]
|
instrs = instrs[:last]
|
||||||
} else {
|
} else if p.state != pkgHasPatch {
|
||||||
// TODO(xsw): confirm pyMod don't need to call AfterInit
|
// TODO(xsw): confirm pyMod don't need to call AfterInit
|
||||||
p.inits = append(p.inits, func() {
|
p.inits = append(p.inits, func() {
|
||||||
pkg.AfterInit(b, ret)
|
pkg.AfterInit(b, ret)
|
||||||
@@ -303,7 +306,7 @@ func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, do
|
|||||||
b.Call(pkg.FuncOf("main.init").Expr)
|
b.Call(pkg.FuncOf("main.init").Expr)
|
||||||
}
|
}
|
||||||
for i, instr := range instrs {
|
for i, instr := range instrs {
|
||||||
if i == 1 && doModInit && p.state == pkgInPatch {
|
if i == 1 && doModInit && p.state == pkgInPatch { // in patch package but no pkgFNoOldInit
|
||||||
initFnNameOld := initFnNameOfHasPatch(p.fn.Name())
|
initFnNameOld := initFnNameOfHasPatch(p.fn.Name())
|
||||||
fnOld := pkg.NewFunc(initFnNameOld, llssa.NoArgsNoRet, llssa.InC)
|
fnOld := pkg.NewFunc(initFnNameOld, llssa.NoArgsNoRet, llssa.InC)
|
||||||
b.Call(fnOld.Expr)
|
b.Call(fnOld.Expr)
|
||||||
|
|||||||
71
cl/import.go
71
cl/import.go
@@ -500,41 +500,6 @@ func (p *context) ensureLoaded(pkgTypes *types.Package) *types.Package {
|
|||||||
return pkgTypes
|
return pkgTypes
|
||||||
}
|
}
|
||||||
|
|
||||||
func pkgKindByPath(pkgPath string) int {
|
|
||||||
switch pkgPath {
|
|
||||||
case "runtime/cgo", "unsafe":
|
|
||||||
return PkgDeclOnly
|
|
||||||
}
|
|
||||||
return PkgNormal
|
|
||||||
}
|
|
||||||
|
|
||||||
func replaceGoName(v string, pos int) string {
|
|
||||||
switch v[:pos] {
|
|
||||||
case "runtime":
|
|
||||||
return "github.com/goplus/llgo/internal/runtime" + v[pos:]
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
func ignoreName(name string) bool {
|
|
||||||
/* TODO(xsw): confirm this is not needed more
|
|
||||||
if name == "unsafe.init" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
const internal = "internal/"
|
|
||||||
return (strings.HasPrefix(name, internal) && !supportedInternal(name[len(internal):])) ||
|
|
||||||
strings.HasPrefix(name, "crypto/") || strings.HasPrefix(name, "runtime/") ||
|
|
||||||
strings.HasPrefix(name, "arena.") || strings.HasPrefix(name, "maps.") ||
|
|
||||||
strings.HasPrefix(name, "plugin.")
|
|
||||||
}
|
|
||||||
|
|
||||||
func supportedInternal(name string) bool {
|
|
||||||
return strings.HasPrefix(name, "abi.") || strings.HasPrefix(name, "bytealg.") ||
|
|
||||||
strings.HasPrefix(name, "oserror.") || strings.HasPrefix(name, "reflectlite.") ||
|
|
||||||
strings.HasPrefix(name, "syscall/unix.") || strings.HasPrefix(name, "syscall/execenv.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -600,3 +565,39 @@ func toBackground(bg string) llssa.Background {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func pkgKindByPath(pkgPath string) int {
|
||||||
|
switch pkgPath {
|
||||||
|
case "runtime/cgo", "unsafe":
|
||||||
|
return PkgDeclOnly
|
||||||
|
}
|
||||||
|
return PkgNormal
|
||||||
|
}
|
||||||
|
|
||||||
|
func replaceGoName(v string, pos int) string {
|
||||||
|
switch v[:pos] {
|
||||||
|
case "runtime":
|
||||||
|
return "github.com/goplus/llgo/internal/runtime" + v[pos:]
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func ignoreName(name string) bool {
|
||||||
|
/* TODO(xsw): confirm this is not needed more
|
||||||
|
if name == "unsafe.init" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
const internal = "internal/"
|
||||||
|
return (strings.HasPrefix(name, internal) && !supportedInternal(name[len(internal):])) ||
|
||||||
|
strings.HasPrefix(name, "runtime/") || strings.HasPrefix(name, "arena.") ||
|
||||||
|
strings.HasPrefix(name, "maps.") || strings.HasPrefix(name, "plugin.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func supportedInternal(name string) bool {
|
||||||
|
return strings.HasPrefix(name, "abi.") || strings.HasPrefix(name, "bytealg.") ||
|
||||||
|
strings.HasPrefix(name, "itoa.") || strings.HasPrefix(name, "oserror.") || strings.HasPrefix(name, "reflectlite.") ||
|
||||||
|
strings.HasPrefix(name, "syscall/unix.") || strings.HasPrefix(name, "syscall/execenv.")
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/goplus/llgo/cmd/internal/base"
|
"github.com/goplus/llgo/cmd/internal/base"
|
||||||
"github.com/goplus/llgo/xtool/env"
|
"github.com/goplus/llgo/x/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
// llgo version
|
// llgo version
|
||||||
|
|||||||
39
cpp/std/std_gc.go
Normal file
39
cpp/std/std_gc.go
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
//go:build !nogc
|
||||||
|
// +build !nogc
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 std
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/bdwgc"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func allocString() *String {
|
||||||
|
ptr := bdwgc.Malloc(unsafe.Sizeof(String{}))
|
||||||
|
bdwgc.RegisterFinalizer(ptr, func(obj, data c.Pointer) {
|
||||||
|
(*String)(obj).Dispose()
|
||||||
|
}, nil, nil, nil)
|
||||||
|
return (*String)(ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
35
cpp/std/std_nogc.go
Normal file
35
cpp/std/std_nogc.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
//go:build nogc
|
||||||
|
// +build nogc
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 std
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func allocString() *String {
|
||||||
|
ptr := c.Malloc(unsafe.Sizeof(String{}))
|
||||||
|
return (*String)(ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
@@ -20,7 +20,6 @@ import (
|
|||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/goplus/llgo/c"
|
"github.com/goplus/llgo/c"
|
||||||
"github.com/goplus/llgo/c/bdwgc"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -32,7 +31,7 @@ type StringView = string
|
|||||||
|
|
||||||
// String represents a C++ std::string object.
|
// String represents a C++ std::string object.
|
||||||
type String struct {
|
type String struct {
|
||||||
Unused [24]byte
|
Unused [3]uintptr
|
||||||
}
|
}
|
||||||
|
|
||||||
// llgo:link (*String).InitEmpty C.stdStringInitEmpty
|
// llgo:link (*String).InitEmpty C.stdStringInitEmpty
|
||||||
@@ -52,14 +51,6 @@ func (s *String) Dispose() {}
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
func allocString() *String {
|
|
||||||
ptr := bdwgc.Malloc(unsafe.Sizeof(String{}))
|
|
||||||
bdwgc.RegisterFinalizer(ptr, func(obj, data c.Pointer) {
|
|
||||||
(*String)(obj).Dispose()
|
|
||||||
}, nil, nil, nil)
|
|
||||||
return (*String)(ptr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewString creates a C++ std::string object.
|
// NewString creates a C++ std::string object.
|
||||||
func NewString(v string) *String {
|
func NewString(v string) *String {
|
||||||
ret := allocString()
|
ret := allocString()
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
# Support a C Library
|
How to support a C/C++ Library
|
||||||
|
=====
|
||||||
|
|
||||||
## Install a C Library
|
## Support a C Library
|
||||||
|
|
||||||
|
### Install a C Library
|
||||||
|
|
||||||
We recommend using a package manager (such as brew, apt-get, winget, etc.) to install a C library. For example:
|
We recommend using a package manager (such as brew, apt-get, winget, etc.) to install a C library. For example:
|
||||||
|
|
||||||
@@ -8,7 +11,7 @@ We recommend using a package manager (such as brew, apt-get, winget, etc.) to in
|
|||||||
brew install inih
|
brew install inih
|
||||||
```
|
```
|
||||||
|
|
||||||
## Writing Go Files to Link Library Functions
|
### Writing Go Files to Link Library Functions
|
||||||
|
|
||||||
1. On macOS, use `nm -gU libbar.dylib` to parse C-style symbols
|
1. On macOS, use `nm -gU libbar.dylib` to parse C-style symbols
|
||||||
|
|
||||||
@@ -85,9 +88,9 @@ cd inih/_demo/inih_demo
|
|||||||
llgo run .
|
llgo run .
|
||||||
```
|
```
|
||||||
|
|
||||||
## Handling Special Types
|
### Handling Special Types
|
||||||
|
|
||||||
### Handling Enum Values in C
|
#### Handling Enum Values in C
|
||||||
|
|
||||||
Use const to implement enum values
|
Use const to implement enum values
|
||||||
|
|
||||||
@@ -119,7 +122,7 @@ const (
|
|||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Handling Structs in C
|
#### Handling Structs in C
|
||||||
|
|
||||||
```go
|
```go
|
||||||
// If you need to use class member variables, like llgo/c/raylib
|
// If you need to use class member variables, like llgo/c/raylib
|
||||||
@@ -176,7 +179,7 @@ func (o *JSON) AddItem(item *JSON) c.Int { return 0 }
|
|||||||
|
|
||||||
For the size of Unused, if the methods bound to the structure do not need to create objects, i.e., the receiver of the Go methods bound to this structure is of pointer type, you can declare `Unused [0]byte`. Otherwise, you need to write a simple C file using the `sizeof` operator to calculate the size of the structure. Assuming the structure size is 38 bytes, then declare `Unused [38]byte`.
|
For the size of Unused, if the methods bound to the structure do not need to create objects, i.e., the receiver of the Go methods bound to this structure is of pointer type, you can declare `Unused [0]byte`. Otherwise, you need to write a simple C file using the `sizeof` operator to calculate the size of the structure. Assuming the structure size is 38 bytes, then declare `Unused [38]byte`.
|
||||||
|
|
||||||
### Handling Function Pointers in C
|
#### Handling Function Pointers in C
|
||||||
|
|
||||||
```go
|
```go
|
||||||
// Convert function pointers to Go style and then declare function pointer types using aliases
|
// Convert function pointers to Go style and then declare function pointer types using aliases
|
||||||
@@ -186,7 +189,7 @@ type Comp func(a c.Int)
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Handling char ** Type in C
|
#### Handling char ** Type in C
|
||||||
|
|
||||||
Handle char ** as `[]*c.Char`
|
Handle char ** as `[]*c.Char`
|
||||||
|
|
||||||
@@ -218,15 +221,15 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
# LLGO for C++ Third-Party Libraries
|
## LLGO for C++ Third-Party Libraries
|
||||||
|
|
||||||
Using the C++ part of the inih library as an example
|
Using the C++ part of the inih library as an example
|
||||||
|
|
||||||
## Installation
|
### Installation
|
||||||
|
|
||||||
Same as installing C libraries
|
Same as installing C libraries
|
||||||
|
|
||||||
## File Structure
|
### File Structure
|
||||||
|
|
||||||
After migrating the C part of the inih library, just continue creating files in the same directory.
|
After migrating the C part of the inih library, just continue creating files in the same directory.
|
||||||
|
|
||||||
@@ -242,9 +245,9 @@ inih/
|
|||||||
└── reader.go
|
└── reader.go
|
||||||
```
|
```
|
||||||
|
|
||||||
## Writing Go Files to Link Library Functions
|
### Writing Go Files to Link Library Functions
|
||||||
|
|
||||||
### Migrating Ordinary Functions
|
#### Migrating Ordinary Functions
|
||||||
|
|
||||||
Since the inih library does not have C++ style ordinary functions, we'll use an ordinary method of a class as an example. The specific process is the same.
|
Since the inih library does not have C++ style ordinary functions, we'll use an ordinary method of a class as an example. The specific process is the same.
|
||||||
|
|
||||||
@@ -283,7 +286,7 @@ For functions, generally use `go:linkname` to link. Here, refer to the migration
|
|||||||
func ParseError() c.Int
|
func ParseError() c.Int
|
||||||
```
|
```
|
||||||
|
|
||||||
### Migrating Classes
|
#### Migrating Classes
|
||||||
|
|
||||||
- Use a struct to map the class. The writing method is the same as migrating a struct in the C library migration:
|
- Use a struct to map the class. The writing method is the same as migrating a struct in the C library migration:
|
||||||
|
|
||||||
@@ -354,7 +357,7 @@ func ParseError() c.Int
|
|||||||
defer reader.Dispose()
|
defer reader.Dispose()
|
||||||
```
|
```
|
||||||
|
|
||||||
### Templates and Inlines
|
#### Templates and Inlines
|
||||||
|
|
||||||
Templates or inlines do not generate symbols in dynamic libraries (dylib) (default constructors and destructors). To ensure that you can use C style symbols to link template or inline functions, create a C++ file and wrap it with `extern "C"`, then bind the functions directly in Go.
|
Templates or inlines do not generate symbols in dynamic libraries (dylib) (default constructors and destructors). To ensure that you can use C style symbols to link template or inline functions, create a C++ file and wrap it with `extern "C"`, then bind the functions directly in Go.
|
||||||
|
|
||||||
@@ -381,7 +384,7 @@ LLGoFiles = "$(pkg-config --cflags spdlog): cppWrap/cppWrap.cpp"
|
|||||||
LLGoPackage = "link: $(pkg-config --libs spdlog); -lspdlog -pthread -lfmt")
|
LLGoPackage = "link: $(pkg-config --libs spdlog); -lspdlog -pthread -lfmt")
|
||||||
```
|
```
|
||||||
|
|
||||||
## Writing and Running the Demo
|
### Writing and Running the Demo
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import (
|
|||||||
"debug/macho"
|
"debug/macho"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
|
"go/build"
|
||||||
"go/constant"
|
"go/constant"
|
||||||
"go/token"
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
@@ -135,7 +136,12 @@ func Do(args []string, conf *Config) {
|
|||||||
|
|
||||||
llssa.Initialize(llssa.InitAll)
|
llssa.Initialize(llssa.InitAll)
|
||||||
|
|
||||||
prog := llssa.NewProgram(nil)
|
target := &llssa.Target{
|
||||||
|
GOOS: build.Default.GOOS,
|
||||||
|
GOARCH: build.Default.GOARCH,
|
||||||
|
}
|
||||||
|
|
||||||
|
prog := llssa.NewProgram(target)
|
||||||
sizes := prog.TypeSizes
|
sizes := prog.TypeSizes
|
||||||
dedup := packages.NewDeduper()
|
dedup := packages.NewDeduper()
|
||||||
dedup.SetPreload(func(pkg *types.Package, files []*ast.File) {
|
dedup.SetPreload(func(pkg *types.Package, files []*ast.File) {
|
||||||
@@ -355,7 +361,11 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, llFiles
|
|||||||
args,
|
args,
|
||||||
"-rpath", "$ORIGIN",
|
"-rpath", "$ORIGIN",
|
||||||
"-rpath", "$ORIGIN/../lib",
|
"-rpath", "$ORIGIN/../lib",
|
||||||
|
"-fdata-sections",
|
||||||
|
"-ffunction-sections",
|
||||||
"-Xlinker", "--gc-sections",
|
"-Xlinker", "--gc-sections",
|
||||||
|
"-lm",
|
||||||
|
"-latomic",
|
||||||
"-lpthread", // libpthread is built-in since glibc 2.34 (2021-08-01); we need to support earlier versions.
|
"-lpthread", // libpthread is built-in since glibc 2.34 (2021-08-01); we need to support earlier versions.
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -747,15 +757,19 @@ func findDylibDep(exe, lib string) string {
|
|||||||
type none struct{}
|
type none struct{}
|
||||||
|
|
||||||
var hasAltPkg = map[string]none{
|
var hasAltPkg = map[string]none{
|
||||||
|
"crypto/md5": {},
|
||||||
"fmt": {},
|
"fmt": {},
|
||||||
|
"hash/crc32": {},
|
||||||
"internal/abi": {},
|
"internal/abi": {},
|
||||||
"internal/bytealg": {},
|
"internal/bytealg": {},
|
||||||
|
"internal/itoa": {},
|
||||||
"internal/oserror": {},
|
"internal/oserror": {},
|
||||||
"internal/reflectlite": {},
|
"internal/reflectlite": {},
|
||||||
"internal/syscall/execenv": {},
|
"internal/syscall/execenv": {},
|
||||||
"internal/syscall/unix": {},
|
"internal/syscall/unix": {},
|
||||||
"math": {},
|
"math": {},
|
||||||
"math/cmplx": {},
|
"math/cmplx": {},
|
||||||
|
"math/rand": {},
|
||||||
"reflect": {},
|
"reflect": {},
|
||||||
"sync": {},
|
"sync": {},
|
||||||
"sync/atomic": {},
|
"sync/atomic": {},
|
||||||
@@ -764,10 +778,7 @@ var hasAltPkg = map[string]none{
|
|||||||
"os": {},
|
"os": {},
|
||||||
"os/exec": {},
|
"os/exec": {},
|
||||||
"runtime": {},
|
"runtime": {},
|
||||||
}
|
"io": {},
|
||||||
|
|
||||||
var overlayFiles = map[string]string{
|
|
||||||
"math/exp_amd64.go": "package math;",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func check(err error) {
|
func check(err error) {
|
||||||
|
|||||||
5
internal/build/overlay.go
Normal file
5
internal/build/overlay.go
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package build
|
||||||
|
|
||||||
|
var overlayFiles = map[string]string{
|
||||||
|
"math/exp_amd64.go": "package math;",
|
||||||
|
}
|
||||||
66
internal/lib/crypto/md5/md5.go
Normal file
66
internal/lib/crypto/md5/md5.go
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* 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 md5
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
import (
|
||||||
|
"hash"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/openssl"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The blocksize of MD5 in bytes.
|
||||||
|
const BlockSize = 64
|
||||||
|
|
||||||
|
// The size of an MD5 checksum in bytes.
|
||||||
|
const Size = 16
|
||||||
|
|
||||||
|
type digest struct {
|
||||||
|
ctx openssl.MD5_CTX
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *digest) Size() int { return Size }
|
||||||
|
|
||||||
|
func (d *digest) BlockSize() int { return BlockSize }
|
||||||
|
|
||||||
|
func (d *digest) Reset() {
|
||||||
|
d.ctx.Init()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *digest) Write(p []byte) (nn int, err error) {
|
||||||
|
d.ctx.UpdateBytes(p)
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *digest) Sum(in []byte) []byte {
|
||||||
|
hash := (*[Size]byte)(c.Alloca(Size))
|
||||||
|
d.ctx.Final((*byte)(unsafe.Pointer(hash)))
|
||||||
|
return append(in, hash[:]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() hash.Hash {
|
||||||
|
d := new(digest)
|
||||||
|
d.ctx.Init()
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
func Sum(data []byte) (ret [Size]byte) {
|
||||||
|
openssl.MD5Bytes(data, &ret[0])
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -1218,7 +1218,6 @@ formatLoop:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *pp) doPrint(a []any) {
|
func (p *pp) doPrint(a []any) {
|
||||||
/*
|
|
||||||
prevString := false
|
prevString := false
|
||||||
for argNum, arg := range a {
|
for argNum, arg := range a {
|
||||||
isString := arg != nil && reflect.TypeOf(arg).Kind() == reflect.String
|
isString := arg != nil && reflect.TypeOf(arg).Kind() == reflect.String
|
||||||
@@ -1229,8 +1228,6 @@ func (p *pp) doPrint(a []any) {
|
|||||||
p.printArg(arg, 'v')
|
p.printArg(arg, 'v')
|
||||||
prevString = isString
|
prevString = isString
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
panic("todo: fmt.(*pp).doPrint")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// doPrintln is like doPrint but always adds a space between arguments
|
// doPrintln is like doPrint but always adds a space between arguments
|
||||||
|
|||||||
112
internal/lib/hash/crc32/crc32.go
Normal file
112
internal/lib/hash/crc32/crc32.go
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* 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 crc32
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
import (
|
||||||
|
"hash"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/zlib"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The size of a CRC-32 checksum in bytes.
|
||||||
|
const Size = 4
|
||||||
|
|
||||||
|
// Predefined polynomials.
|
||||||
|
const (
|
||||||
|
// IEEE is by far and away the most common CRC-32 polynomial.
|
||||||
|
// Used by ethernet (IEEE 802.3), v.42, fddi, gzip, zip, png, ...
|
||||||
|
IEEE = 0xedb88320
|
||||||
|
|
||||||
|
// Castagnoli's polynomial, used in iSCSI.
|
||||||
|
// Has better error detection characteristics than IEEE.
|
||||||
|
// https://dx.doi.org/10.1109/26.231911
|
||||||
|
Castagnoli = 0x82f63b78
|
||||||
|
|
||||||
|
// Koopman's polynomial.
|
||||||
|
// Also has better error detection characteristics than IEEE.
|
||||||
|
// https://dx.doi.org/10.1109/DSN.2002.1028931
|
||||||
|
Koopman = 0xeb31d82e
|
||||||
|
)
|
||||||
|
|
||||||
|
// Table is a 256-word table representing the polynomial for efficient processing.
|
||||||
|
type Table [256]uint32
|
||||||
|
|
||||||
|
// IEEETable is the table for the IEEE polynomial.
|
||||||
|
var IEEETable *Table = new(Table)
|
||||||
|
|
||||||
|
// MakeTable returns a Table constructed from the specified polynomial.
|
||||||
|
// The contents of this Table must not be modified.
|
||||||
|
func MakeTable(poly uint32) *Table {
|
||||||
|
if poly == IEEE {
|
||||||
|
return IEEETable
|
||||||
|
}
|
||||||
|
panic("todo: hash/crc32.MakeTable")
|
||||||
|
}
|
||||||
|
|
||||||
|
type digest uint32
|
||||||
|
|
||||||
|
func (d *digest) Size() int { return Size }
|
||||||
|
|
||||||
|
func (d *digest) BlockSize() int { return 1 }
|
||||||
|
|
||||||
|
func (d *digest) Reset() { *d = 0 }
|
||||||
|
|
||||||
|
func (d *digest) Write(p []byte) (n int, err error) {
|
||||||
|
*d = digest(zlib.Crc32ZBytes(c.Ulong(*d), p))
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *digest) Sum32() uint32 { return uint32(*d) }
|
||||||
|
|
||||||
|
func (d *digest) Sum(in []byte) []byte {
|
||||||
|
s := d.Sum32()
|
||||||
|
return append(in, byte(s>>24), byte(s>>16), byte(s>>8), byte(s))
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(tab *Table) hash.Hash32 {
|
||||||
|
if tab == IEEETable {
|
||||||
|
return new(digest)
|
||||||
|
}
|
||||||
|
panic("todo: hash/crc32.New")
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewIEEE creates a new hash.Hash32 computing the CRC-32 checksum using
|
||||||
|
// the IEEE polynomial. Its Sum method will lay the value out in
|
||||||
|
// big-endian byte order. The returned Hash32 also implements
|
||||||
|
// encoding.BinaryMarshaler and encoding.BinaryUnmarshaler to marshal
|
||||||
|
// and unmarshal the internal state of the hash.
|
||||||
|
func NewIEEE() hash.Hash32 { return New(IEEETable) }
|
||||||
|
|
||||||
|
// Update returns the result of adding the bytes in p to the crc.
|
||||||
|
func Update(crc uint32, tab *Table, p []byte) uint32 {
|
||||||
|
if tab == IEEETable {
|
||||||
|
return uint32(zlib.Crc32ZBytes(c.Ulong(crc), p))
|
||||||
|
}
|
||||||
|
panic("todo: hash/crc32.Update")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checksum returns the CRC-32 checksum of data
|
||||||
|
// using the polynomial represented by the Table.
|
||||||
|
func Checksum(data []byte, tab *Table) uint32 { return Update(0, tab, data) }
|
||||||
|
|
||||||
|
// ChecksumIEEE returns the CRC-32 checksum of data
|
||||||
|
// using the IEEE polynomial.
|
||||||
|
func ChecksumIEEE(data []byte) uint32 {
|
||||||
|
return uint32(zlib.Crc32ZBytes(0, data))
|
||||||
|
}
|
||||||
34
internal/lib/internal/itoa/itoa.go
Normal file
34
internal/lib/internal/itoa/itoa.go
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
// Copyright 2021 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.
|
||||||
|
|
||||||
|
// Simple conversions to avoid depending on strconv.
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
package itoa
|
||||||
|
|
||||||
|
// Itoa converts val to a decimal string.
|
||||||
|
func Itoa(val int) string {
|
||||||
|
if val < 0 {
|
||||||
|
return "-" + Uitoa(uint(-val))
|
||||||
|
}
|
||||||
|
return Uitoa(uint(val))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uitoa converts val to a decimal string.
|
||||||
|
func Uitoa(val uint) string {
|
||||||
|
if val == 0 { // avoid string allocation
|
||||||
|
return "0"
|
||||||
|
}
|
||||||
|
var buf [20]byte // big enough for 64bit value base 10
|
||||||
|
i := len(buf) - 1
|
||||||
|
for val >= 10 {
|
||||||
|
q := val / 10
|
||||||
|
buf[i] = byte('0' + val - q*10)
|
||||||
|
i--
|
||||||
|
val = q
|
||||||
|
}
|
||||||
|
// val < 10
|
||||||
|
buf[i] = byte('0' + val)
|
||||||
|
return string(buf[i:])
|
||||||
|
}
|
||||||
207
internal/lib/io/pipe.go
Normal file
207
internal/lib/io/pipe.go
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
// Pipe adapter to connect code expecting an io.Reader
|
||||||
|
// with code expecting an io.Writer.
|
||||||
|
|
||||||
|
package io
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// onceError is an object that will only store an error once.
|
||||||
|
type onceError struct {
|
||||||
|
sync.Mutex // guards following
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *onceError) Store(err error) {
|
||||||
|
a.Lock()
|
||||||
|
defer a.Unlock()
|
||||||
|
if a.err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
a.err = err
|
||||||
|
}
|
||||||
|
func (a *onceError) Load() error {
|
||||||
|
a.Lock()
|
||||||
|
defer a.Unlock()
|
||||||
|
return a.err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrClosedPipe is the error used for read or write operations on a closed pipe.
|
||||||
|
var ErrClosedPipe = errors.New("io: read/write on closed pipe")
|
||||||
|
|
||||||
|
// A pipe is the shared pipe structure underlying PipeReader and PipeWriter.
|
||||||
|
type pipe struct {
|
||||||
|
wrMu sync.Mutex // Serializes Write operations
|
||||||
|
wrCh chan []byte
|
||||||
|
rdCh chan int
|
||||||
|
|
||||||
|
once sync.Once // Protects closing done
|
||||||
|
done chan struct{}
|
||||||
|
rerr onceError
|
||||||
|
werr onceError
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *pipe) read(b []byte) (n int, err error) {
|
||||||
|
select {
|
||||||
|
case <-p.done:
|
||||||
|
return 0, p.readCloseError()
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case bw := <-p.wrCh:
|
||||||
|
nr := copy(b, bw)
|
||||||
|
p.rdCh <- nr
|
||||||
|
return nr, nil
|
||||||
|
case <-p.done:
|
||||||
|
return 0, p.readCloseError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *pipe) closeRead(err error) error {
|
||||||
|
if err == nil {
|
||||||
|
err = ErrClosedPipe
|
||||||
|
}
|
||||||
|
p.rerr.Store(err)
|
||||||
|
p.once.Do(func() { close(p.done) })
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *pipe) write(b []byte) (n int, err error) {
|
||||||
|
select {
|
||||||
|
case <-p.done:
|
||||||
|
return 0, p.writeCloseError()
|
||||||
|
default:
|
||||||
|
p.wrMu.Lock()
|
||||||
|
defer p.wrMu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
for once := true; once || len(b) > 0; once = false {
|
||||||
|
select {
|
||||||
|
case p.wrCh <- b:
|
||||||
|
nw := <-p.rdCh
|
||||||
|
b = b[nw:]
|
||||||
|
n += nw
|
||||||
|
case <-p.done:
|
||||||
|
return n, p.writeCloseError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *pipe) closeWrite(err error) error {
|
||||||
|
if err == nil {
|
||||||
|
err = io.EOF
|
||||||
|
}
|
||||||
|
p.werr.Store(err)
|
||||||
|
p.once.Do(func() { close(p.done) })
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// readCloseError is considered internal to the pipe type.
|
||||||
|
func (p *pipe) readCloseError() error {
|
||||||
|
rerr := p.rerr.Load()
|
||||||
|
if werr := p.werr.Load(); rerr == nil && werr != nil {
|
||||||
|
return werr
|
||||||
|
}
|
||||||
|
return ErrClosedPipe
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeCloseError is considered internal to the pipe type.
|
||||||
|
func (p *pipe) writeCloseError() error {
|
||||||
|
werr := p.werr.Load()
|
||||||
|
if rerr := p.rerr.Load(); werr == nil && rerr != nil {
|
||||||
|
return rerr
|
||||||
|
}
|
||||||
|
return ErrClosedPipe
|
||||||
|
}
|
||||||
|
|
||||||
|
// A PipeReader is the read half of a pipe.
|
||||||
|
type PipeReader struct {
|
||||||
|
p *pipe
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read implements the standard Read interface:
|
||||||
|
// it reads data from the pipe, blocking until a writer
|
||||||
|
// arrives or the write end is closed.
|
||||||
|
// If the write end is closed with an error, that error is
|
||||||
|
// returned as err; otherwise err is EOF.
|
||||||
|
func (r *PipeReader) Read(data []byte) (n int, err error) {
|
||||||
|
return r.p.read(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the reader; subsequent writes to the
|
||||||
|
// write half of the pipe will return the error ErrClosedPipe.
|
||||||
|
func (r *PipeReader) Close() error {
|
||||||
|
return r.CloseWithError(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloseWithError closes the reader; subsequent writes
|
||||||
|
// to the write half of the pipe will return the error err.
|
||||||
|
//
|
||||||
|
// CloseWithError never overwrites the previous error if it exists
|
||||||
|
// and always returns nil.
|
||||||
|
func (r *PipeReader) CloseWithError(err error) error {
|
||||||
|
return r.p.closeRead(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A PipeWriter is the write half of a pipe.
|
||||||
|
type PipeWriter struct {
|
||||||
|
p *pipe
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write implements the standard Write interface:
|
||||||
|
// it writes data to the pipe, blocking until one or more readers
|
||||||
|
// have consumed all the data or the read end is closed.
|
||||||
|
// If the read end is closed with an error, that err is
|
||||||
|
// returned as err; otherwise err is ErrClosedPipe.
|
||||||
|
func (w *PipeWriter) Write(data []byte) (n int, err error) {
|
||||||
|
return w.p.write(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the writer; subsequent reads from the
|
||||||
|
// read half of the pipe will return no bytes and EOF.
|
||||||
|
func (w *PipeWriter) Close() error {
|
||||||
|
return w.CloseWithError(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloseWithError closes the writer; subsequent reads from the
|
||||||
|
// read half of the pipe will return no bytes and the error err,
|
||||||
|
// or EOF if err is nil.
|
||||||
|
//
|
||||||
|
// CloseWithError never overwrites the previous error if it exists
|
||||||
|
// and always returns nil.
|
||||||
|
func (w *PipeWriter) CloseWithError(err error) error {
|
||||||
|
return w.p.closeWrite(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pipe creates a synchronous in-memory pipe.
|
||||||
|
// It can be used to connect code expecting an io.Reader
|
||||||
|
// with code expecting an io.Writer.
|
||||||
|
//
|
||||||
|
// Reads and Writes on the pipe are matched one to one
|
||||||
|
// except when multiple Reads are needed to consume a single Write.
|
||||||
|
// That is, each Write to the PipeWriter blocks until it has satisfied
|
||||||
|
// one or more Reads from the PipeReader that fully consume
|
||||||
|
// the written data.
|
||||||
|
// The data is copied directly from the Write to the corresponding
|
||||||
|
// Read (or Reads); there is no internal buffering.
|
||||||
|
//
|
||||||
|
// It is safe to call Read and Write in parallel with each other or with Close.
|
||||||
|
// Parallel calls to Read and parallel calls to Write are also safe:
|
||||||
|
// the individual calls will be gated sequentially.
|
||||||
|
func Pipe() (*PipeReader, *PipeWriter) {
|
||||||
|
p := &pipe{
|
||||||
|
wrCh: make(chan []byte, 1),
|
||||||
|
rdCh: make(chan int, 1),
|
||||||
|
done: make(chan struct{}, 1),
|
||||||
|
}
|
||||||
|
return &PipeReader{p}, &PipeWriter{p}
|
||||||
|
}
|
||||||
221
internal/lib/math/rand/exp.go
Normal file
221
internal/lib/math/rand/exp.go
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
// 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 rand
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exponential distribution
|
||||||
|
*
|
||||||
|
* See "The Ziggurat Method for Generating Random Variables"
|
||||||
|
* (Marsaglia & Tsang, 2000)
|
||||||
|
* https://www.jstatsoft.org/v05/i08/paper [pdf]
|
||||||
|
*/
|
||||||
|
|
||||||
|
const (
|
||||||
|
re = 7.69711747013104972
|
||||||
|
)
|
||||||
|
|
||||||
|
// ExpFloat64 returns an exponentially distributed float64 in the range
|
||||||
|
// (0, +math.MaxFloat64] with an exponential distribution whose rate parameter
|
||||||
|
// (lambda) is 1 and whose mean is 1/lambda (1).
|
||||||
|
// To produce a distribution with a different rate parameter,
|
||||||
|
// callers can adjust the output using:
|
||||||
|
//
|
||||||
|
// sample = ExpFloat64() / desiredRateParameter
|
||||||
|
func (r *Rand) ExpFloat64() float64 {
|
||||||
|
for {
|
||||||
|
j := r.Uint32()
|
||||||
|
i := j & 0xFF
|
||||||
|
x := float64(j) * float64(we[i])
|
||||||
|
if j < ke[i] {
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
if i == 0 {
|
||||||
|
return re - math.Log(r.Float64())
|
||||||
|
}
|
||||||
|
if fe[i]+float32(r.Float64())*(fe[i-1]-fe[i]) < float32(math.Exp(-x)) {
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var ke = [256]uint32{
|
||||||
|
0xe290a139, 0x0, 0x9beadebc, 0xc377ac71, 0xd4ddb990,
|
||||||
|
0xde893fb8, 0xe4a8e87c, 0xe8dff16a, 0xebf2deab, 0xee49a6e8,
|
||||||
|
0xf0204efd, 0xf19bdb8e, 0xf2d458bb, 0xf3da104b, 0xf4b86d78,
|
||||||
|
0xf577ad8a, 0xf61de83d, 0xf6afb784, 0xf730a573, 0xf7a37651,
|
||||||
|
0xf80a5bb6, 0xf867189d, 0xf8bb1b4f, 0xf9079062, 0xf94d70ca,
|
||||||
|
0xf98d8c7d, 0xf9c8928a, 0xf9ff175b, 0xfa319996, 0xfa6085f8,
|
||||||
|
0xfa8c3a62, 0xfab5084e, 0xfadb36c8, 0xfaff0410, 0xfb20a6ea,
|
||||||
|
0xfb404fb4, 0xfb5e2951, 0xfb7a59e9, 0xfb95038c, 0xfbae44ba,
|
||||||
|
0xfbc638d8, 0xfbdcf892, 0xfbf29a30, 0xfc0731df, 0xfc1ad1ed,
|
||||||
|
0xfc2d8b02, 0xfc3f6c4d, 0xfc5083ac, 0xfc60ddd1, 0xfc708662,
|
||||||
|
0xfc7f8810, 0xfc8decb4, 0xfc9bbd62, 0xfca9027c, 0xfcb5c3c3,
|
||||||
|
0xfcc20864, 0xfccdd70a, 0xfcd935e3, 0xfce42ab0, 0xfceebace,
|
||||||
|
0xfcf8eb3b, 0xfd02c0a0, 0xfd0c3f59, 0xfd156b7b, 0xfd1e48d6,
|
||||||
|
0xfd26daff, 0xfd2f2552, 0xfd372af7, 0xfd3eeee5, 0xfd4673e7,
|
||||||
|
0xfd4dbc9e, 0xfd54cb85, 0xfd5ba2f2, 0xfd62451b, 0xfd68b415,
|
||||||
|
0xfd6ef1da, 0xfd750047, 0xfd7ae120, 0xfd809612, 0xfd8620b4,
|
||||||
|
0xfd8b8285, 0xfd90bcf5, 0xfd95d15e, 0xfd9ac10b, 0xfd9f8d36,
|
||||||
|
0xfda43708, 0xfda8bf9e, 0xfdad2806, 0xfdb17141, 0xfdb59c46,
|
||||||
|
0xfdb9a9fd, 0xfdbd9b46, 0xfdc170f6, 0xfdc52bd8, 0xfdc8ccac,
|
||||||
|
0xfdcc542d, 0xfdcfc30b, 0xfdd319ef, 0xfdd6597a, 0xfdd98245,
|
||||||
|
0xfddc94e5, 0xfddf91e6, 0xfde279ce, 0xfde54d1f, 0xfde80c52,
|
||||||
|
0xfdeab7de, 0xfded5034, 0xfdefd5be, 0xfdf248e3, 0xfdf4aa06,
|
||||||
|
0xfdf6f984, 0xfdf937b6, 0xfdfb64f4, 0xfdfd818d, 0xfdff8dd0,
|
||||||
|
0xfe018a08, 0xfe03767a, 0xfe05536c, 0xfe07211c, 0xfe08dfc9,
|
||||||
|
0xfe0a8fab, 0xfe0c30fb, 0xfe0dc3ec, 0xfe0f48b1, 0xfe10bf76,
|
||||||
|
0xfe122869, 0xfe1383b4, 0xfe14d17c, 0xfe1611e7, 0xfe174516,
|
||||||
|
0xfe186b2a, 0xfe19843e, 0xfe1a9070, 0xfe1b8fd6, 0xfe1c8289,
|
||||||
|
0xfe1d689b, 0xfe1e4220, 0xfe1f0f26, 0xfe1fcfbc, 0xfe2083ed,
|
||||||
|
0xfe212bc3, 0xfe21c745, 0xfe225678, 0xfe22d95f, 0xfe234ffb,
|
||||||
|
0xfe23ba4a, 0xfe241849, 0xfe2469f2, 0xfe24af3c, 0xfe24e81e,
|
||||||
|
0xfe25148b, 0xfe253474, 0xfe2547c7, 0xfe254e70, 0xfe25485a,
|
||||||
|
0xfe25356a, 0xfe251586, 0xfe24e88f, 0xfe24ae64, 0xfe2466e1,
|
||||||
|
0xfe2411df, 0xfe23af34, 0xfe233eb4, 0xfe22c02c, 0xfe22336b,
|
||||||
|
0xfe219838, 0xfe20ee58, 0xfe20358c, 0xfe1f6d92, 0xfe1e9621,
|
||||||
|
0xfe1daef0, 0xfe1cb7ac, 0xfe1bb002, 0xfe1a9798, 0xfe196e0d,
|
||||||
|
0xfe1832fd, 0xfe16e5fe, 0xfe15869d, 0xfe141464, 0xfe128ed3,
|
||||||
|
0xfe10f565, 0xfe0f478c, 0xfe0d84b1, 0xfe0bac36, 0xfe09bd73,
|
||||||
|
0xfe07b7b5, 0xfe059a40, 0xfe03644c, 0xfe011504, 0xfdfeab88,
|
||||||
|
0xfdfc26e9, 0xfdf98629, 0xfdf6c83b, 0xfdf3ec01, 0xfdf0f04a,
|
||||||
|
0xfdedd3d1, 0xfdea953d, 0xfde7331e, 0xfde3abe9, 0xfddffdfb,
|
||||||
|
0xfddc2791, 0xfdd826cd, 0xfdd3f9a8, 0xfdcf9dfc, 0xfdcb1176,
|
||||||
|
0xfdc65198, 0xfdc15bb3, 0xfdbc2ce2, 0xfdb6c206, 0xfdb117be,
|
||||||
|
0xfdab2a63, 0xfda4f5fd, 0xfd9e7640, 0xfd97a67a, 0xfd908192,
|
||||||
|
0xfd8901f2, 0xfd812182, 0xfd78d98e, 0xfd7022bb, 0xfd66f4ed,
|
||||||
|
0xfd5d4732, 0xfd530f9c, 0xfd48432b, 0xfd3cd59a, 0xfd30b936,
|
||||||
|
0xfd23dea4, 0xfd16349e, 0xfd07a7a3, 0xfcf8219b, 0xfce7895b,
|
||||||
|
0xfcd5c220, 0xfcc2aadb, 0xfcae1d5e, 0xfc97ed4e, 0xfc7fe6d4,
|
||||||
|
0xfc65ccf3, 0xfc495762, 0xfc2a2fc8, 0xfc07ee19, 0xfbe213c1,
|
||||||
|
0xfbb8051a, 0xfb890078, 0xfb5411a5, 0xfb180005, 0xfad33482,
|
||||||
|
0xfa839276, 0xfa263b32, 0xf9b72d1c, 0xf930a1a2, 0xf889f023,
|
||||||
|
0xf7b577d2, 0xf69c650c, 0xf51530f0, 0xf2cb0e3c, 0xeeefb15d,
|
||||||
|
0xe6da6ecf,
|
||||||
|
}
|
||||||
|
var we = [256]float32{
|
||||||
|
2.0249555e-09, 1.486674e-11, 2.4409617e-11, 3.1968806e-11,
|
||||||
|
3.844677e-11, 4.4228204e-11, 4.9516443e-11, 5.443359e-11,
|
||||||
|
5.905944e-11, 6.344942e-11, 6.7643814e-11, 7.1672945e-11,
|
||||||
|
7.556032e-11, 7.932458e-11, 8.298079e-11, 8.654132e-11,
|
||||||
|
9.0016515e-11, 9.3415074e-11, 9.674443e-11, 1.0001099e-10,
|
||||||
|
1.03220314e-10, 1.06377254e-10, 1.09486115e-10, 1.1255068e-10,
|
||||||
|
1.1557435e-10, 1.1856015e-10, 1.2151083e-10, 1.2442886e-10,
|
||||||
|
1.2731648e-10, 1.3017575e-10, 1.3300853e-10, 1.3581657e-10,
|
||||||
|
1.3860142e-10, 1.4136457e-10, 1.4410738e-10, 1.4683108e-10,
|
||||||
|
1.4953687e-10, 1.5222583e-10, 1.54899e-10, 1.5755733e-10,
|
||||||
|
1.6020171e-10, 1.6283301e-10, 1.6545203e-10, 1.6805951e-10,
|
||||||
|
1.7065617e-10, 1.732427e-10, 1.7581973e-10, 1.7838787e-10,
|
||||||
|
1.8094774e-10, 1.8349985e-10, 1.8604476e-10, 1.8858298e-10,
|
||||||
|
1.9111498e-10, 1.9364126e-10, 1.9616223e-10, 1.9867835e-10,
|
||||||
|
2.0119004e-10, 2.0369768e-10, 2.0620168e-10, 2.087024e-10,
|
||||||
|
2.1120022e-10, 2.136955e-10, 2.1618855e-10, 2.1867974e-10,
|
||||||
|
2.2116936e-10, 2.2365775e-10, 2.261452e-10, 2.2863202e-10,
|
||||||
|
2.311185e-10, 2.3360494e-10, 2.360916e-10, 2.3857874e-10,
|
||||||
|
2.4106667e-10, 2.4355562e-10, 2.4604588e-10, 2.485377e-10,
|
||||||
|
2.5103128e-10, 2.5352695e-10, 2.560249e-10, 2.585254e-10,
|
||||||
|
2.6102867e-10, 2.6353494e-10, 2.6604446e-10, 2.6855745e-10,
|
||||||
|
2.7107416e-10, 2.7359479e-10, 2.761196e-10, 2.7864877e-10,
|
||||||
|
2.8118255e-10, 2.8372119e-10, 2.8626485e-10, 2.888138e-10,
|
||||||
|
2.9136826e-10, 2.939284e-10, 2.9649452e-10, 2.9906677e-10,
|
||||||
|
3.016454e-10, 3.0423064e-10, 3.0682268e-10, 3.0942177e-10,
|
||||||
|
3.1202813e-10, 3.1464195e-10, 3.1726352e-10, 3.19893e-10,
|
||||||
|
3.2253064e-10, 3.251767e-10, 3.2783135e-10, 3.3049485e-10,
|
||||||
|
3.3316744e-10, 3.3584938e-10, 3.3854083e-10, 3.4124212e-10,
|
||||||
|
3.4395342e-10, 3.46675e-10, 3.4940711e-10, 3.5215003e-10,
|
||||||
|
3.5490397e-10, 3.5766917e-10, 3.6044595e-10, 3.6323455e-10,
|
||||||
|
3.660352e-10, 3.6884823e-10, 3.7167386e-10, 3.745124e-10,
|
||||||
|
3.773641e-10, 3.802293e-10, 3.8310827e-10, 3.860013e-10,
|
||||||
|
3.8890866e-10, 3.918307e-10, 3.9476775e-10, 3.9772008e-10,
|
||||||
|
4.0068804e-10, 4.0367196e-10, 4.0667217e-10, 4.09689e-10,
|
||||||
|
4.1272286e-10, 4.1577405e-10, 4.1884296e-10, 4.2192994e-10,
|
||||||
|
4.250354e-10, 4.281597e-10, 4.313033e-10, 4.3446652e-10,
|
||||||
|
4.3764986e-10, 4.408537e-10, 4.4407847e-10, 4.4732465e-10,
|
||||||
|
4.5059267e-10, 4.5388301e-10, 4.571962e-10, 4.6053267e-10,
|
||||||
|
4.6389292e-10, 4.6727755e-10, 4.70687e-10, 4.741219e-10,
|
||||||
|
4.7758275e-10, 4.810702e-10, 4.845848e-10, 4.8812715e-10,
|
||||||
|
4.9169796e-10, 4.9529775e-10, 4.989273e-10, 5.0258725e-10,
|
||||||
|
5.0627835e-10, 5.100013e-10, 5.1375687e-10, 5.1754584e-10,
|
||||||
|
5.21369e-10, 5.2522725e-10, 5.2912136e-10, 5.330522e-10,
|
||||||
|
5.370208e-10, 5.4102806e-10, 5.45075e-10, 5.491625e-10,
|
||||||
|
5.532918e-10, 5.5746385e-10, 5.616799e-10, 5.6594107e-10,
|
||||||
|
5.7024857e-10, 5.746037e-10, 5.7900773e-10, 5.834621e-10,
|
||||||
|
5.8796823e-10, 5.925276e-10, 5.971417e-10, 6.018122e-10,
|
||||||
|
6.065408e-10, 6.113292e-10, 6.1617933e-10, 6.2109295e-10,
|
||||||
|
6.260722e-10, 6.3111916e-10, 6.3623595e-10, 6.4142497e-10,
|
||||||
|
6.4668854e-10, 6.5202926e-10, 6.5744976e-10, 6.6295286e-10,
|
||||||
|
6.6854156e-10, 6.742188e-10, 6.79988e-10, 6.858526e-10,
|
||||||
|
6.9181616e-10, 6.978826e-10, 7.04056e-10, 7.103407e-10,
|
||||||
|
7.167412e-10, 7.2326256e-10, 7.2990985e-10, 7.366886e-10,
|
||||||
|
7.4360473e-10, 7.5066453e-10, 7.5787476e-10, 7.6524265e-10,
|
||||||
|
7.7277595e-10, 7.80483e-10, 7.883728e-10, 7.9645507e-10,
|
||||||
|
8.047402e-10, 8.1323964e-10, 8.219657e-10, 8.309319e-10,
|
||||||
|
8.401528e-10, 8.496445e-10, 8.594247e-10, 8.6951274e-10,
|
||||||
|
8.799301e-10, 8.9070046e-10, 9.018503e-10, 9.134092e-10,
|
||||||
|
9.254101e-10, 9.378904e-10, 9.508923e-10, 9.644638e-10,
|
||||||
|
9.786603e-10, 9.935448e-10, 1.0091913e-09, 1.025686e-09,
|
||||||
|
1.0431306e-09, 1.0616465e-09, 1.08138e-09, 1.1025096e-09,
|
||||||
|
1.1252564e-09, 1.1498986e-09, 1.1767932e-09, 1.206409e-09,
|
||||||
|
1.2393786e-09, 1.276585e-09, 1.3193139e-09, 1.3695435e-09,
|
||||||
|
1.4305498e-09, 1.508365e-09, 1.6160854e-09, 1.7921248e-09,
|
||||||
|
}
|
||||||
|
var fe = [256]float32{
|
||||||
|
1, 0.9381437, 0.90046996, 0.87170434, 0.8477855, 0.8269933,
|
||||||
|
0.8084217, 0.7915276, 0.77595687, 0.7614634, 0.7478686,
|
||||||
|
0.7350381, 0.72286767, 0.71127474, 0.70019263, 0.6895665,
|
||||||
|
0.67935055, 0.6695063, 0.66000086, 0.65080583, 0.6418967,
|
||||||
|
0.63325197, 0.6248527, 0.6166822, 0.60872537, 0.60096896,
|
||||||
|
0.5934009, 0.58601034, 0.5787874, 0.57172304, 0.5648092,
|
||||||
|
0.5580383, 0.5514034, 0.5448982, 0.5385169, 0.53225386,
|
||||||
|
0.5261042, 0.52006316, 0.5141264, 0.50828975, 0.5025495,
|
||||||
|
0.496902, 0.49134386, 0.485872, 0.48048335, 0.4751752,
|
||||||
|
0.46994483, 0.46478975, 0.45970762, 0.45469615, 0.44975325,
|
||||||
|
0.44487688, 0.44006512, 0.43531612, 0.43062815, 0.42599955,
|
||||||
|
0.42142874, 0.4169142, 0.41245446, 0.40804818, 0.403694,
|
||||||
|
0.3993907, 0.39513698, 0.39093173, 0.38677382, 0.38266218,
|
||||||
|
0.37859577, 0.37457356, 0.37059465, 0.3666581, 0.362763,
|
||||||
|
0.35890847, 0.35509375, 0.351318, 0.3475805, 0.34388044,
|
||||||
|
0.34021714, 0.3365899, 0.33299807, 0.32944095, 0.32591796,
|
||||||
|
0.3224285, 0.3189719, 0.31554767, 0.31215525, 0.30879408,
|
||||||
|
0.3054636, 0.3021634, 0.29889292, 0.2956517, 0.29243928,
|
||||||
|
0.28925523, 0.28609908, 0.28297043, 0.27986884, 0.27679393,
|
||||||
|
0.2737453, 0.2707226, 0.2677254, 0.26475343, 0.26180625,
|
||||||
|
0.25888354, 0.25598502, 0.2531103, 0.25025907, 0.24743107,
|
||||||
|
0.24462597, 0.24184346, 0.23908329, 0.23634516, 0.23362878,
|
||||||
|
0.23093392, 0.2282603, 0.22560766, 0.22297576, 0.22036438,
|
||||||
|
0.21777324, 0.21520215, 0.21265087, 0.21011916, 0.20760682,
|
||||||
|
0.20511365, 0.20263945, 0.20018397, 0.19774707, 0.19532852,
|
||||||
|
0.19292815, 0.19054577, 0.1881812, 0.18583426, 0.18350479,
|
||||||
|
0.1811926, 0.17889754, 0.17661946, 0.17435817, 0.17211354,
|
||||||
|
0.1698854, 0.16767362, 0.16547804, 0.16329853, 0.16113494,
|
||||||
|
0.15898713, 0.15685499, 0.15473837, 0.15263714, 0.15055119,
|
||||||
|
0.14848037, 0.14642459, 0.14438373, 0.14235765, 0.14034624,
|
||||||
|
0.13834943, 0.13636707, 0.13439907, 0.13244532, 0.13050574,
|
||||||
|
0.1285802, 0.12666863, 0.12477092, 0.12288698, 0.12101672,
|
||||||
|
0.119160056, 0.1173169, 0.115487166, 0.11367077, 0.11186763,
|
||||||
|
0.11007768, 0.10830083, 0.10653701, 0.10478614, 0.10304816,
|
||||||
|
0.101323, 0.09961058, 0.09791085, 0.09622374, 0.09454919,
|
||||||
|
0.09288713, 0.091237515, 0.08960028, 0.087975375, 0.08636274,
|
||||||
|
0.08476233, 0.083174095, 0.081597984, 0.08003395, 0.07848195,
|
||||||
|
0.076941945, 0.07541389, 0.07389775, 0.072393484, 0.07090106,
|
||||||
|
0.069420435, 0.06795159, 0.066494495, 0.06504912, 0.063615434,
|
||||||
|
0.062193416, 0.060783047, 0.059384305, 0.057997175,
|
||||||
|
0.05662164, 0.05525769, 0.053905312, 0.052564494, 0.051235236,
|
||||||
|
0.049917534, 0.048611384, 0.047316793, 0.046033762, 0.0447623,
|
||||||
|
0.043502413, 0.042254124, 0.041017443, 0.039792392,
|
||||||
|
0.038578995, 0.037377283, 0.036187284, 0.035009038,
|
||||||
|
0.033842582, 0.032687962, 0.031545233, 0.030414443, 0.02929566,
|
||||||
|
0.02818895, 0.027094385, 0.026012046, 0.024942026, 0.023884421,
|
||||||
|
0.022839336, 0.021806888, 0.020787204, 0.019780423, 0.0187867,
|
||||||
|
0.0178062, 0.016839107, 0.015885621, 0.014945968, 0.014020392,
|
||||||
|
0.013109165, 0.012212592, 0.011331013, 0.01046481, 0.009614414,
|
||||||
|
0.008780315, 0.007963077, 0.0071633533, 0.006381906,
|
||||||
|
0.0056196423, 0.0048776558, 0.004157295, 0.0034602648,
|
||||||
|
0.0027887989, 0.0021459677, 0.0015362998, 0.0009672693,
|
||||||
|
0.00045413437,
|
||||||
|
}
|
||||||
156
internal/lib/math/rand/normal.go
Normal file
156
internal/lib/math/rand/normal.go
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
// 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 rand
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Normal distribution
|
||||||
|
*
|
||||||
|
* See "The Ziggurat Method for Generating Random Variables"
|
||||||
|
* (Marsaglia & Tsang, 2000)
|
||||||
|
* http://www.jstatsoft.org/v05/i08/paper [pdf]
|
||||||
|
*/
|
||||||
|
|
||||||
|
const (
|
||||||
|
rn = 3.442619855899
|
||||||
|
)
|
||||||
|
|
||||||
|
func absInt32(i int32) uint32 {
|
||||||
|
if i < 0 {
|
||||||
|
return uint32(-i)
|
||||||
|
}
|
||||||
|
return uint32(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NormFloat64 returns a normally distributed float64 in
|
||||||
|
// the range -math.MaxFloat64 through +math.MaxFloat64 inclusive,
|
||||||
|
// with standard normal distribution (mean = 0, stddev = 1).
|
||||||
|
// To produce a different normal distribution, callers can
|
||||||
|
// adjust the output using:
|
||||||
|
//
|
||||||
|
// sample = NormFloat64() * desiredStdDev + desiredMean
|
||||||
|
func (r *Rand) NormFloat64() float64 {
|
||||||
|
for {
|
||||||
|
j := int32(r.Uint32()) // Possibly negative
|
||||||
|
i := j & 0x7F
|
||||||
|
x := float64(j) * float64(wn[i])
|
||||||
|
if absInt32(j) < kn[i] {
|
||||||
|
// This case should be hit better than 99% of the time.
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
if i == 0 {
|
||||||
|
// This extra work is only required for the base strip.
|
||||||
|
for {
|
||||||
|
x = -math.Log(r.Float64()) * (1.0 / rn)
|
||||||
|
y := -math.Log(r.Float64())
|
||||||
|
if y+y >= x*x {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if j > 0 {
|
||||||
|
return rn + x
|
||||||
|
}
|
||||||
|
return -rn - x
|
||||||
|
}
|
||||||
|
if fn[i]+float32(r.Float64())*(fn[i-1]-fn[i]) < float32(math.Exp(-.5*x*x)) {
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var kn = [128]uint32{
|
||||||
|
0x76ad2212, 0x0, 0x600f1b53, 0x6ce447a6, 0x725b46a2,
|
||||||
|
0x7560051d, 0x774921eb, 0x789a25bd, 0x799045c3, 0x7a4bce5d,
|
||||||
|
0x7adf629f, 0x7b5682a6, 0x7bb8a8c6, 0x7c0ae722, 0x7c50cce7,
|
||||||
|
0x7c8cec5b, 0x7cc12cd6, 0x7ceefed2, 0x7d177e0b, 0x7d3b8883,
|
||||||
|
0x7d5bce6c, 0x7d78dd64, 0x7d932886, 0x7dab0e57, 0x7dc0dd30,
|
||||||
|
0x7dd4d688, 0x7de73185, 0x7df81cea, 0x7e07c0a3, 0x7e163efa,
|
||||||
|
0x7e23b587, 0x7e303dfd, 0x7e3beec2, 0x7e46db77, 0x7e51155d,
|
||||||
|
0x7e5aabb3, 0x7e63abf7, 0x7e6c222c, 0x7e741906, 0x7e7b9a18,
|
||||||
|
0x7e82adfa, 0x7e895c63, 0x7e8fac4b, 0x7e95a3fb, 0x7e9b4924,
|
||||||
|
0x7ea0a0ef, 0x7ea5b00d, 0x7eaa7ac3, 0x7eaf04f3, 0x7eb3522a,
|
||||||
|
0x7eb765a5, 0x7ebb4259, 0x7ebeeafd, 0x7ec2620a, 0x7ec5a9c4,
|
||||||
|
0x7ec8c441, 0x7ecbb365, 0x7ece78ed, 0x7ed11671, 0x7ed38d62,
|
||||||
|
0x7ed5df12, 0x7ed80cb4, 0x7eda175c, 0x7edc0005, 0x7eddc78e,
|
||||||
|
0x7edf6ebf, 0x7ee0f647, 0x7ee25ebe, 0x7ee3a8a9, 0x7ee4d473,
|
||||||
|
0x7ee5e276, 0x7ee6d2f5, 0x7ee7a620, 0x7ee85c10, 0x7ee8f4cd,
|
||||||
|
0x7ee97047, 0x7ee9ce59, 0x7eea0eca, 0x7eea3147, 0x7eea3568,
|
||||||
|
0x7eea1aab, 0x7ee9e071, 0x7ee98602, 0x7ee90a88, 0x7ee86d08,
|
||||||
|
0x7ee7ac6a, 0x7ee6c769, 0x7ee5bc9c, 0x7ee48a67, 0x7ee32efc,
|
||||||
|
0x7ee1a857, 0x7edff42f, 0x7ede0ffa, 0x7edbf8d9, 0x7ed9ab94,
|
||||||
|
0x7ed7248d, 0x7ed45fae, 0x7ed1585c, 0x7ece095f, 0x7eca6ccb,
|
||||||
|
0x7ec67be2, 0x7ec22eee, 0x7ebd7d1a, 0x7eb85c35, 0x7eb2c075,
|
||||||
|
0x7eac9c20, 0x7ea5df27, 0x7e9e769f, 0x7e964c16, 0x7e8d44ba,
|
||||||
|
0x7e834033, 0x7e781728, 0x7e6b9933, 0x7e5d8a1a, 0x7e4d9ded,
|
||||||
|
0x7e3b737a, 0x7e268c2f, 0x7e0e3ff5, 0x7df1aa5d, 0x7dcf8c72,
|
||||||
|
0x7da61a1e, 0x7d72a0fb, 0x7d30e097, 0x7cd9b4ab, 0x7c600f1a,
|
||||||
|
0x7ba90bdc, 0x7a722176, 0x77d664e5,
|
||||||
|
}
|
||||||
|
var wn = [128]float32{
|
||||||
|
1.7290405e-09, 1.2680929e-10, 1.6897518e-10, 1.9862688e-10,
|
||||||
|
2.2232431e-10, 2.4244937e-10, 2.601613e-10, 2.7611988e-10,
|
||||||
|
2.9073963e-10, 3.042997e-10, 3.1699796e-10, 3.289802e-10,
|
||||||
|
3.4035738e-10, 3.5121603e-10, 3.616251e-10, 3.7164058e-10,
|
||||||
|
3.8130857e-10, 3.9066758e-10, 3.9975012e-10, 4.08584e-10,
|
||||||
|
4.1719309e-10, 4.2559822e-10, 4.338176e-10, 4.418672e-10,
|
||||||
|
4.497613e-10, 4.5751258e-10, 4.651324e-10, 4.7263105e-10,
|
||||||
|
4.8001775e-10, 4.87301e-10, 4.944885e-10, 5.015873e-10,
|
||||||
|
5.0860405e-10, 5.155446e-10, 5.2241467e-10, 5.2921934e-10,
|
||||||
|
5.359635e-10, 5.426517e-10, 5.4928817e-10, 5.5587696e-10,
|
||||||
|
5.624219e-10, 5.6892646e-10, 5.753941e-10, 5.818282e-10,
|
||||||
|
5.882317e-10, 5.946077e-10, 6.00959e-10, 6.072884e-10,
|
||||||
|
6.135985e-10, 6.19892e-10, 6.2617134e-10, 6.3243905e-10,
|
||||||
|
6.386974e-10, 6.449488e-10, 6.511956e-10, 6.5744005e-10,
|
||||||
|
6.6368433e-10, 6.699307e-10, 6.7618144e-10, 6.824387e-10,
|
||||||
|
6.8870465e-10, 6.949815e-10, 7.012715e-10, 7.075768e-10,
|
||||||
|
7.1389966e-10, 7.202424e-10, 7.266073e-10, 7.329966e-10,
|
||||||
|
7.394128e-10, 7.4585826e-10, 7.5233547e-10, 7.58847e-10,
|
||||||
|
7.653954e-10, 7.719835e-10, 7.7861395e-10, 7.852897e-10,
|
||||||
|
7.920138e-10, 7.987892e-10, 8.0561924e-10, 8.125073e-10,
|
||||||
|
8.194569e-10, 8.2647167e-10, 8.3355556e-10, 8.407127e-10,
|
||||||
|
8.479473e-10, 8.55264e-10, 8.6266755e-10, 8.7016316e-10,
|
||||||
|
8.777562e-10, 8.8545243e-10, 8.932582e-10, 9.0117996e-10,
|
||||||
|
9.09225e-10, 9.174008e-10, 9.2571584e-10, 9.341788e-10,
|
||||||
|
9.427997e-10, 9.515889e-10, 9.605579e-10, 9.697193e-10,
|
||||||
|
9.790869e-10, 9.88676e-10, 9.985036e-10, 1.0085882e-09,
|
||||||
|
1.0189509e-09, 1.0296151e-09, 1.0406069e-09, 1.0519566e-09,
|
||||||
|
1.063698e-09, 1.0758702e-09, 1.0885183e-09, 1.1016947e-09,
|
||||||
|
1.1154611e-09, 1.1298902e-09, 1.1450696e-09, 1.1611052e-09,
|
||||||
|
1.1781276e-09, 1.1962995e-09, 1.2158287e-09, 1.2369856e-09,
|
||||||
|
1.2601323e-09, 1.2857697e-09, 1.3146202e-09, 1.347784e-09,
|
||||||
|
1.3870636e-09, 1.4357403e-09, 1.5008659e-09, 1.6030948e-09,
|
||||||
|
}
|
||||||
|
var fn = [128]float32{
|
||||||
|
1, 0.9635997, 0.9362827, 0.9130436, 0.89228165, 0.87324303,
|
||||||
|
0.8555006, 0.8387836, 0.8229072, 0.8077383, 0.793177,
|
||||||
|
0.7791461, 0.7655842, 0.7524416, 0.73967725, 0.7272569,
|
||||||
|
0.7151515, 0.7033361, 0.69178915, 0.68049186, 0.6694277,
|
||||||
|
0.658582, 0.6479418, 0.63749546, 0.6272325, 0.6171434,
|
||||||
|
0.6072195, 0.5974532, 0.58783704, 0.5783647, 0.56903,
|
||||||
|
0.5598274, 0.5507518, 0.54179835, 0.5329627, 0.52424055,
|
||||||
|
0.5156282, 0.50712204, 0.49871865, 0.49041483, 0.48220766,
|
||||||
|
0.4740943, 0.46607214, 0.4581387, 0.45029163, 0.44252872,
|
||||||
|
0.43484783, 0.427247, 0.41972435, 0.41227803, 0.40490642,
|
||||||
|
0.39760786, 0.3903808, 0.3832238, 0.37613547, 0.36911446,
|
||||||
|
0.3621595, 0.35526937, 0.34844297, 0.34167916, 0.33497685,
|
||||||
|
0.3283351, 0.3217529, 0.3152294, 0.30876362, 0.30235484,
|
||||||
|
0.29600215, 0.28970486, 0.2834622, 0.2772735, 0.27113807,
|
||||||
|
0.2650553, 0.25902456, 0.2530453, 0.24711695, 0.241239,
|
||||||
|
0.23541094, 0.22963232, 0.2239027, 0.21822165, 0.21258877,
|
||||||
|
0.20700371, 0.20146611, 0.19597565, 0.19053204, 0.18513499,
|
||||||
|
0.17978427, 0.17447963, 0.1692209, 0.16400786, 0.15884037,
|
||||||
|
0.15371831, 0.14864157, 0.14361008, 0.13862377, 0.13368265,
|
||||||
|
0.12878671, 0.12393598, 0.119130544, 0.11437051, 0.10965602,
|
||||||
|
0.104987256, 0.10036444, 0.095787846, 0.0912578, 0.08677467,
|
||||||
|
0.0823389, 0.077950984, 0.073611505, 0.06932112, 0.06508058,
|
||||||
|
0.06089077, 0.056752663, 0.0526674, 0.048636295, 0.044660863,
|
||||||
|
0.040742867, 0.03688439, 0.033087887, 0.029356318,
|
||||||
|
0.025693292, 0.022103304, 0.018592102, 0.015167298,
|
||||||
|
0.011839478, 0.008624485, 0.005548995, 0.0026696292,
|
||||||
|
}
|
||||||
547
internal/lib/math/rand/rand.go
Normal file
547
internal/lib/math/rand/rand.go
Normal file
@@ -0,0 +1,547 @@
|
|||||||
|
// 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 rand implements pseudo-random number generators suitable for tasks
|
||||||
|
// such as simulation, but it should not be used for security-sensitive work.
|
||||||
|
//
|
||||||
|
// Random numbers are generated by a [Source], usually wrapped in a [Rand].
|
||||||
|
// Both types should be used by a single goroutine at a time: sharing among
|
||||||
|
// multiple goroutines requires some kind of synchronization.
|
||||||
|
//
|
||||||
|
// Top-level functions, such as [Float64] and [Int],
|
||||||
|
// are safe for concurrent use by multiple goroutines.
|
||||||
|
//
|
||||||
|
// This package's outputs might be easily predictable regardless of how it's
|
||||||
|
// seeded. For random numbers suitable for security-sensitive work, see the
|
||||||
|
// crypto/rand package.
|
||||||
|
package rand
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
_ "unsafe" // for go:linkname
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/math/rand"
|
||||||
|
"github.com/goplus/llgo/c/time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Source represents a source of uniformly-distributed
|
||||||
|
// pseudo-random int64 values in the range [0, 1<<63).
|
||||||
|
//
|
||||||
|
// A Source is not safe for concurrent use by multiple goroutines.
|
||||||
|
type Source interface {
|
||||||
|
Int63() int64
|
||||||
|
Seed(seed int64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Source64 is a Source that can also generate
|
||||||
|
// uniformly-distributed pseudo-random uint64 values in
|
||||||
|
// the range [0, 1<<64) directly.
|
||||||
|
// If a Rand r's underlying Source s implements Source64,
|
||||||
|
// then r.Uint64 returns the result of one call to s.Uint64
|
||||||
|
// instead of making two calls to s.Int63.
|
||||||
|
type Source64 interface {
|
||||||
|
Source
|
||||||
|
Uint64() uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSource returns a new pseudo-random Source seeded with the given value.
|
||||||
|
// Unlike the default Source used by top-level functions, this source is not
|
||||||
|
// safe for concurrent use by multiple goroutines.
|
||||||
|
// The returned Source implements Source64.
|
||||||
|
func NewSource(seed int64) Source {
|
||||||
|
return newSource(seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSource(seed int64) *rngSource {
|
||||||
|
var rng rngSource
|
||||||
|
rng.Seed(seed)
|
||||||
|
return &rng
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Rand is a source of random numbers.
|
||||||
|
type Rand struct {
|
||||||
|
src Source
|
||||||
|
s64 Source64 // non-nil if src is source64
|
||||||
|
|
||||||
|
// readVal contains remainder of 63-bit integer used for bytes
|
||||||
|
// generation during most recent Read call.
|
||||||
|
// It is saved so next Read call can start where the previous
|
||||||
|
// one finished.
|
||||||
|
readVal int64
|
||||||
|
// readPos indicates the number of low-order bytes of readVal
|
||||||
|
// that are still valid.
|
||||||
|
readPos int8
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new Rand that uses random values from src
|
||||||
|
// to generate other random values.
|
||||||
|
func New(src Source) *Rand {
|
||||||
|
s64, _ := src.(Source64)
|
||||||
|
return &Rand{src: src, s64: s64}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seed uses the provided seed value to initialize the generator to a deterministic state.
|
||||||
|
// Seed should not be called concurrently with any other Rand method.
|
||||||
|
func (r *Rand) Seed(seed int64) {
|
||||||
|
if lk, ok := r.src.(*lockedSource); ok {
|
||||||
|
lk.seedPos(seed, &r.readPos)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
r.src.Seed(seed)
|
||||||
|
r.readPos = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int63 returns a non-negative pseudo-random 63-bit integer as an int64.
|
||||||
|
func (r *Rand) Int63() int64 { return r.src.Int63() }
|
||||||
|
|
||||||
|
// Uint32 returns a pseudo-random 32-bit value as a uint32.
|
||||||
|
func (r *Rand) Uint32() uint32 { return uint32(r.Int63() >> 31) }
|
||||||
|
|
||||||
|
// Uint64 returns a pseudo-random 64-bit value as a uint64.
|
||||||
|
func (r *Rand) Uint64() uint64 {
|
||||||
|
if r.s64 != nil {
|
||||||
|
return r.s64.Uint64()
|
||||||
|
}
|
||||||
|
return uint64(r.Int63())>>31 | uint64(r.Int63())<<32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int31 returns a non-negative pseudo-random 31-bit integer as an int32.
|
||||||
|
func (r *Rand) Int31() int32 { return int32(r.Int63() >> 32) }
|
||||||
|
|
||||||
|
// Int returns a non-negative pseudo-random int.
|
||||||
|
func (r *Rand) Int() int {
|
||||||
|
u := uint(r.Int63())
|
||||||
|
return int(u << 1 >> 1) // clear sign bit if int == int32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int63n returns, as an int64, a non-negative pseudo-random number in the half-open interval [0,n).
|
||||||
|
// It panics if n <= 0.
|
||||||
|
func (r *Rand) Int63n(n int64) int64 {
|
||||||
|
if n <= 0 {
|
||||||
|
panic("invalid argument to Int63n")
|
||||||
|
}
|
||||||
|
if n&(n-1) == 0 { // n is power of two, can mask
|
||||||
|
return r.Int63() & (n - 1)
|
||||||
|
}
|
||||||
|
max := int64((1 << 63) - 1 - (1<<63)%uint64(n))
|
||||||
|
v := r.Int63()
|
||||||
|
for v > max {
|
||||||
|
v = r.Int63()
|
||||||
|
}
|
||||||
|
return v % n
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int31n returns, as an int32, a non-negative pseudo-random number in the half-open interval [0,n).
|
||||||
|
// It panics if n <= 0.
|
||||||
|
func (r *Rand) Int31n(n int32) int32 {
|
||||||
|
if n <= 0 {
|
||||||
|
panic("invalid argument to Int31n")
|
||||||
|
}
|
||||||
|
if n&(n-1) == 0 { // n is power of two, can mask
|
||||||
|
return r.Int31() & (n - 1)
|
||||||
|
}
|
||||||
|
max := int32((1 << 31) - 1 - (1<<31)%uint32(n))
|
||||||
|
v := r.Int31()
|
||||||
|
for v > max {
|
||||||
|
v = r.Int31()
|
||||||
|
}
|
||||||
|
return v % n
|
||||||
|
}
|
||||||
|
|
||||||
|
// int31n returns, as an int32, a non-negative pseudo-random number in the half-open interval [0,n).
|
||||||
|
// n must be > 0, but int31n does not check this; the caller must ensure it.
|
||||||
|
// int31n exists because Int31n is inefficient, but Go 1 compatibility
|
||||||
|
// requires that the stream of values produced by math/rand remain unchanged.
|
||||||
|
// int31n can thus only be used internally, by newly introduced APIs.
|
||||||
|
//
|
||||||
|
// For implementation details, see:
|
||||||
|
// https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction
|
||||||
|
// https://lemire.me/blog/2016/06/30/fast-random-shuffling
|
||||||
|
func (r *Rand) int31n(n int32) int32 {
|
||||||
|
v := r.Uint32()
|
||||||
|
prod := uint64(v) * uint64(n)
|
||||||
|
low := uint32(prod)
|
||||||
|
if low < uint32(n) {
|
||||||
|
thresh := uint32(-n) % uint32(n)
|
||||||
|
for low < thresh {
|
||||||
|
v = r.Uint32()
|
||||||
|
prod = uint64(v) * uint64(n)
|
||||||
|
low = uint32(prod)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return int32(prod >> 32)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intn returns, as an int, a non-negative pseudo-random number in the half-open interval [0,n).
|
||||||
|
// It panics if n <= 0.
|
||||||
|
func (r *Rand) Intn(n int) int {
|
||||||
|
if n <= 0 {
|
||||||
|
panic("invalid argument to Intn")
|
||||||
|
}
|
||||||
|
if n <= 1<<31-1 {
|
||||||
|
return int(r.Int31n(int32(n)))
|
||||||
|
}
|
||||||
|
return int(r.Int63n(int64(n)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64 returns, as a float64, a pseudo-random number in the half-open interval [0.0,1.0).
|
||||||
|
func (r *Rand) Float64() float64 {
|
||||||
|
// A clearer, simpler implementation would be:
|
||||||
|
// return float64(r.Int63n(1<<53)) / (1<<53)
|
||||||
|
// However, Go 1 shipped with
|
||||||
|
// return float64(r.Int63()) / (1 << 63)
|
||||||
|
// and we want to preserve that value stream.
|
||||||
|
//
|
||||||
|
// There is one bug in the value stream: r.Int63() may be so close
|
||||||
|
// to 1<<63 that the division rounds up to 1.0, and we've guaranteed
|
||||||
|
// that the result is always less than 1.0.
|
||||||
|
//
|
||||||
|
// We tried to fix this by mapping 1.0 back to 0.0, but since float64
|
||||||
|
// values near 0 are much denser than near 1, mapping 1 to 0 caused
|
||||||
|
// a theoretically significant overshoot in the probability of returning 0.
|
||||||
|
// Instead of that, if we round up to 1, just try again.
|
||||||
|
// Getting 1 only happens 1/2⁵³ of the time, so most clients
|
||||||
|
// will not observe it anyway.
|
||||||
|
again:
|
||||||
|
f := float64(r.Int63()) / (1 << 63)
|
||||||
|
if f == 1 {
|
||||||
|
goto again // resample; this branch is taken O(never)
|
||||||
|
}
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float32 returns, as a float32, a pseudo-random number in the half-open interval [0.0,1.0).
|
||||||
|
func (r *Rand) Float32() float32 {
|
||||||
|
// Same rationale as in Float64: we want to preserve the Go 1 value
|
||||||
|
// stream except we want to fix it not to return 1.0
|
||||||
|
// This only happens 1/2²⁴ of the time (plus the 1/2⁵³ of the time in Float64).
|
||||||
|
again:
|
||||||
|
f := float32(r.Float64())
|
||||||
|
if f == 1 {
|
||||||
|
goto again // resample; this branch is taken O(very rarely)
|
||||||
|
}
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers
|
||||||
|
// in the half-open interval [0,n).
|
||||||
|
func (r *Rand) Perm(n int) []int {
|
||||||
|
m := make([]int, n)
|
||||||
|
// In the following loop, the iteration when i=0 always swaps m[0] with m[0].
|
||||||
|
// A change to remove this useless iteration is to assign 1 to i in the init
|
||||||
|
// statement. But Perm also effects r. Making this change will affect
|
||||||
|
// the final state of r. So this change can't be made for compatibility
|
||||||
|
// reasons for Go 1.
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
j := r.Intn(i + 1)
|
||||||
|
m[i] = m[j]
|
||||||
|
m[j] = i
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shuffle pseudo-randomizes the order of elements.
|
||||||
|
// n is the number of elements. Shuffle panics if n < 0.
|
||||||
|
// swap swaps the elements with indexes i and j.
|
||||||
|
func (r *Rand) Shuffle(n int, swap func(i, j int)) {
|
||||||
|
if n < 0 {
|
||||||
|
panic("invalid argument to Shuffle")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fisher-Yates shuffle: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
|
||||||
|
// Shuffle really ought not be called with n that doesn't fit in 32 bits.
|
||||||
|
// Not only will it take a very long time, but with 2³¹! possible permutations,
|
||||||
|
// there's no way that any PRNG can have a big enough internal state to
|
||||||
|
// generate even a minuscule percentage of the possible permutations.
|
||||||
|
// Nevertheless, the right API signature accepts an int n, so handle it as best we can.
|
||||||
|
i := n - 1
|
||||||
|
for ; i > 1<<31-1-1; i-- {
|
||||||
|
j := int(r.Int63n(int64(i + 1)))
|
||||||
|
swap(i, j)
|
||||||
|
}
|
||||||
|
for ; i > 0; i-- {
|
||||||
|
j := int(r.int31n(int32(i + 1)))
|
||||||
|
swap(i, j)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read generates len(p) random bytes and writes them into p. It
|
||||||
|
// always returns len(p) and a nil error.
|
||||||
|
// Read should not be called concurrently with any other Rand method.
|
||||||
|
func (r *Rand) Read(p []byte) (n int, err error) {
|
||||||
|
switch src := r.src.(type) {
|
||||||
|
case *lockedSource:
|
||||||
|
return src.read(p, &r.readVal, &r.readPos)
|
||||||
|
case *fastSource:
|
||||||
|
return src.read(p, &r.readVal, &r.readPos)
|
||||||
|
}
|
||||||
|
return read(p, r.src, &r.readVal, &r.readPos)
|
||||||
|
}
|
||||||
|
|
||||||
|
func read(p []byte, src Source, readVal *int64, readPos *int8) (n int, err error) {
|
||||||
|
pos := *readPos
|
||||||
|
val := *readVal
|
||||||
|
rng, _ := src.(*rngSource)
|
||||||
|
for n = 0; n < len(p); n++ {
|
||||||
|
if pos == 0 {
|
||||||
|
if rng != nil {
|
||||||
|
val = rng.Int63()
|
||||||
|
} else {
|
||||||
|
val = src.Int63()
|
||||||
|
}
|
||||||
|
pos = 7
|
||||||
|
}
|
||||||
|
p[n] = byte(val)
|
||||||
|
val >>= 8
|
||||||
|
pos--
|
||||||
|
}
|
||||||
|
*readPos = pos
|
||||||
|
*readVal = val
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Top-level convenience functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
// globalRandGenerator is the source of random numbers for the top-level
|
||||||
|
// convenience functions. When possible it uses the runtime fastrand64
|
||||||
|
// function to avoid locking. This is not possible if the user called Seed,
|
||||||
|
// either explicitly or implicitly via GODEBUG=randautoseed=0.
|
||||||
|
var globalRandGenerator atomic.Pointer[Rand]
|
||||||
|
|
||||||
|
// globalRand returns the generator to use for the top-level convenience
|
||||||
|
// functions.
|
||||||
|
func globalRand() *Rand {
|
||||||
|
if r := globalRandGenerator.Load(); r != nil {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the first call. Initialize based on GODEBUG.
|
||||||
|
var r = &Rand{
|
||||||
|
src: &fastSource{},
|
||||||
|
s64: &fastSource{},
|
||||||
|
}
|
||||||
|
if !globalRandGenerator.CompareAndSwap(nil, r) {
|
||||||
|
// Two different goroutines called some top-level
|
||||||
|
// function at the same time. While the results in
|
||||||
|
// that case are unpredictable, if we just use r here,
|
||||||
|
// and we are using a seed, we will most likely return
|
||||||
|
// the same value for both calls. That doesn't seem ideal.
|
||||||
|
// Just use the first one to get in.
|
||||||
|
return globalRandGenerator.Load()
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func fastrand64() uint64 {
|
||||||
|
v1 := uint64(rand.Random())
|
||||||
|
v2 := uint64(rand.Random())
|
||||||
|
return v1 ^ (v2 << 32)
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rand.Srandom(c.Uint(time.Time(nil)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// fastSource is an implementation of Source64 that uses the runtime
|
||||||
|
// fastrand functions.
|
||||||
|
type fastSource struct {
|
||||||
|
// The mutex is used to avoid race conditions in Read.
|
||||||
|
mu sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*fastSource) Int63() int64 {
|
||||||
|
return int64(fastrand64() & rngMask)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*fastSource) Seed(int64) {
|
||||||
|
panic("internal error: call to fastSource.Seed")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*fastSource) Uint64() uint64 {
|
||||||
|
return fastrand64()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs *fastSource) read(p []byte, readVal *int64, readPos *int8) (n int, err error) {
|
||||||
|
fs.mu.Lock()
|
||||||
|
n, err = read(p, fs, readVal, readPos)
|
||||||
|
fs.mu.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seed uses the provided seed value to initialize the default Source to a
|
||||||
|
// deterministic state. Seed values that have the same remainder when
|
||||||
|
// divided by 2³¹-1 generate the same pseudo-random sequence.
|
||||||
|
// Seed, unlike the Rand.Seed method, is safe for concurrent use.
|
||||||
|
//
|
||||||
|
// If Seed is not called, the generator is seeded randomly at program startup.
|
||||||
|
//
|
||||||
|
// Prior to Go 1.20, the generator was seeded like Seed(1) at program startup.
|
||||||
|
// To force the old behavior, call Seed(1) at program startup.
|
||||||
|
// Alternately, set GODEBUG=randautoseed=0 in the environment
|
||||||
|
// before making any calls to functions in this package.
|
||||||
|
//
|
||||||
|
// Deprecated: As of Go 1.20 there is no reason to call Seed with
|
||||||
|
// a random value. Programs that call Seed with a known value to get
|
||||||
|
// a specific sequence of results should use New(NewSource(seed)) to
|
||||||
|
// obtain a local random generator.
|
||||||
|
func Seed(seed int64) {
|
||||||
|
orig := globalRandGenerator.Load()
|
||||||
|
|
||||||
|
// If we are already using a lockedSource, we can just re-seed it.
|
||||||
|
if orig != nil {
|
||||||
|
if _, ok := orig.src.(*lockedSource); ok {
|
||||||
|
orig.Seed(seed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise either
|
||||||
|
// 1) orig == nil, which is the normal case when Seed is the first
|
||||||
|
// top-level function to be called, or
|
||||||
|
// 2) orig is already a fastSource, in which case we need to change
|
||||||
|
// to a lockedSource.
|
||||||
|
// Either way we do the same thing.
|
||||||
|
|
||||||
|
r := New(new(lockedSource))
|
||||||
|
r.Seed(seed)
|
||||||
|
|
||||||
|
if !globalRandGenerator.CompareAndSwap(orig, r) {
|
||||||
|
// Something changed underfoot. Retry to be safe.
|
||||||
|
Seed(seed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int63 returns a non-negative pseudo-random 63-bit integer as an int64
|
||||||
|
// from the default Source.
|
||||||
|
func Int63() int64 { return globalRand().Int63() }
|
||||||
|
|
||||||
|
// Uint32 returns a pseudo-random 32-bit value as a uint32
|
||||||
|
// from the default Source.
|
||||||
|
func Uint32() uint32 { return globalRand().Uint32() }
|
||||||
|
|
||||||
|
// Uint64 returns a pseudo-random 64-bit value as a uint64
|
||||||
|
// from the default Source.
|
||||||
|
func Uint64() uint64 { return globalRand().Uint64() }
|
||||||
|
|
||||||
|
// Int31 returns a non-negative pseudo-random 31-bit integer as an int32
|
||||||
|
// from the default Source.
|
||||||
|
func Int31() int32 { return globalRand().Int31() }
|
||||||
|
|
||||||
|
// Int returns a non-negative pseudo-random int from the default Source.
|
||||||
|
func Int() int { return globalRand().Int() }
|
||||||
|
|
||||||
|
// Int63n returns, as an int64, a non-negative pseudo-random number in the half-open interval [0,n)
|
||||||
|
// from the default Source.
|
||||||
|
// It panics if n <= 0.
|
||||||
|
func Int63n(n int64) int64 { return globalRand().Int63n(n) }
|
||||||
|
|
||||||
|
// Int31n returns, as an int32, a non-negative pseudo-random number in the half-open interval [0,n)
|
||||||
|
// from the default Source.
|
||||||
|
// It panics if n <= 0.
|
||||||
|
func Int31n(n int32) int32 { return globalRand().Int31n(n) }
|
||||||
|
|
||||||
|
// Intn returns, as an int, a non-negative pseudo-random number in the half-open interval [0,n)
|
||||||
|
// from the default Source.
|
||||||
|
// It panics if n <= 0.
|
||||||
|
func Intn(n int) int { return globalRand().Intn(n) }
|
||||||
|
|
||||||
|
// Float64 returns, as a float64, a pseudo-random number in the half-open interval [0.0,1.0)
|
||||||
|
// from the default Source.
|
||||||
|
func Float64() float64 { return globalRand().Float64() }
|
||||||
|
|
||||||
|
// Float32 returns, as a float32, a pseudo-random number in the half-open interval [0.0,1.0)
|
||||||
|
// from the default Source.
|
||||||
|
func Float32() float32 { return globalRand().Float32() }
|
||||||
|
|
||||||
|
// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers
|
||||||
|
// in the half-open interval [0,n) from the default Source.
|
||||||
|
func Perm(n int) []int { return globalRand().Perm(n) }
|
||||||
|
|
||||||
|
// Shuffle pseudo-randomizes the order of elements using the default Source.
|
||||||
|
// n is the number of elements. Shuffle panics if n < 0.
|
||||||
|
// swap swaps the elements with indexes i and j.
|
||||||
|
func Shuffle(n int, swap func(i, j int)) { globalRand().Shuffle(n, swap) }
|
||||||
|
|
||||||
|
// Read generates len(p) random bytes from the default Source and
|
||||||
|
// writes them into p. It always returns len(p) and a nil error.
|
||||||
|
// Read, unlike the Rand.Read method, is safe for concurrent use.
|
||||||
|
//
|
||||||
|
// Deprecated: For almost all use cases, crypto/rand.Read is more appropriate.
|
||||||
|
func Read(p []byte) (n int, err error) { return globalRand().Read(p) }
|
||||||
|
|
||||||
|
// NormFloat64 returns a normally distributed float64 in the range
|
||||||
|
// [-math.MaxFloat64, +math.MaxFloat64] with
|
||||||
|
// standard normal distribution (mean = 0, stddev = 1)
|
||||||
|
// from the default Source.
|
||||||
|
// To produce a different normal distribution, callers can
|
||||||
|
// adjust the output using:
|
||||||
|
//
|
||||||
|
// sample = NormFloat64() * desiredStdDev + desiredMean
|
||||||
|
func NormFloat64() float64 { return globalRand().NormFloat64() }
|
||||||
|
|
||||||
|
// ExpFloat64 returns an exponentially distributed float64 in the range
|
||||||
|
// (0, +math.MaxFloat64] with an exponential distribution whose rate parameter
|
||||||
|
// (lambda) is 1 and whose mean is 1/lambda (1) from the default Source.
|
||||||
|
// To produce a distribution with a different rate parameter,
|
||||||
|
// callers can adjust the output using:
|
||||||
|
//
|
||||||
|
// sample = ExpFloat64() / desiredRateParameter
|
||||||
|
func ExpFloat64() float64 { return globalRand().ExpFloat64() }
|
||||||
|
|
||||||
|
type lockedSource struct {
|
||||||
|
lk sync.Mutex
|
||||||
|
s *rngSource
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *lockedSource) Int63() (n int64) {
|
||||||
|
r.lk.Lock()
|
||||||
|
n = r.s.Int63()
|
||||||
|
r.lk.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *lockedSource) Uint64() (n uint64) {
|
||||||
|
r.lk.Lock()
|
||||||
|
n = r.s.Uint64()
|
||||||
|
r.lk.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *lockedSource) Seed(seed int64) {
|
||||||
|
r.lk.Lock()
|
||||||
|
r.seed(seed)
|
||||||
|
r.lk.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// seedPos implements Seed for a lockedSource without a race condition.
|
||||||
|
func (r *lockedSource) seedPos(seed int64, readPos *int8) {
|
||||||
|
r.lk.Lock()
|
||||||
|
r.seed(seed)
|
||||||
|
*readPos = 0
|
||||||
|
r.lk.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// seed seeds the underlying source.
|
||||||
|
// The caller must have locked r.lk.
|
||||||
|
func (r *lockedSource) seed(seed int64) {
|
||||||
|
if r.s == nil {
|
||||||
|
r.s = newSource(seed)
|
||||||
|
} else {
|
||||||
|
r.s.Seed(seed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// read implements Read for a lockedSource without a race condition.
|
||||||
|
func (r *lockedSource) read(p []byte, readVal *int64, readPos *int8) (n int, err error) {
|
||||||
|
r.lk.Lock()
|
||||||
|
n, err = read(p, r.s, readVal, readPos)
|
||||||
|
r.lk.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
252
internal/lib/math/rand/rng.go
Normal file
252
internal/lib/math/rand/rng.go
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
// 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 rand
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Uniform distribution
|
||||||
|
*
|
||||||
|
* algorithm by
|
||||||
|
* DP Mitchell and JA Reeds
|
||||||
|
*/
|
||||||
|
|
||||||
|
const (
|
||||||
|
rngLen = 607
|
||||||
|
rngTap = 273
|
||||||
|
rngMax = 1 << 63
|
||||||
|
rngMask = rngMax - 1
|
||||||
|
int32max = (1 << 31) - 1
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// rngCooked used for seeding. See gen_cooked.go for details.
|
||||||
|
rngCooked [rngLen]int64 = [...]int64{
|
||||||
|
-4181792142133755926, -4576982950128230565, 1395769623340756751, 5333664234075297259,
|
||||||
|
-6347679516498800754, 9033628115061424579, 7143218595135194537, 4812947590706362721,
|
||||||
|
7937252194349799378, 5307299880338848416, 8209348851763925077, -7107630437535961764,
|
||||||
|
4593015457530856296, 8140875735541888011, -5903942795589686782, -603556388664454774,
|
||||||
|
-7496297993371156308, 113108499721038619, 4569519971459345583, -4160538177779461077,
|
||||||
|
-6835753265595711384, -6507240692498089696, 6559392774825876886, 7650093201692370310,
|
||||||
|
7684323884043752161, -8965504200858744418, -2629915517445760644, 271327514973697897,
|
||||||
|
-6433985589514657524, 1065192797246149621, 3344507881999356393, -4763574095074709175,
|
||||||
|
7465081662728599889, 1014950805555097187, -4773931307508785033, -5742262670416273165,
|
||||||
|
2418672789110888383, 5796562887576294778, 4484266064449540171, 3738982361971787048,
|
||||||
|
-4699774852342421385, 10530508058128498, -589538253572429690, -6598062107225984180,
|
||||||
|
8660405965245884302, 10162832508971942, -2682657355892958417, 7031802312784620857,
|
||||||
|
6240911277345944669, 831864355460801054, -1218937899312622917, 2116287251661052151,
|
||||||
|
2202309800992166967, 9161020366945053561, 4069299552407763864, 4936383537992622449,
|
||||||
|
457351505131524928, -8881176990926596454, -6375600354038175299, -7155351920868399290,
|
||||||
|
4368649989588021065, 887231587095185257, -3659780529968199312, -2407146836602825512,
|
||||||
|
5616972787034086048, -751562733459939242, 1686575021641186857, -5177887698780513806,
|
||||||
|
-4979215821652996885, -1375154703071198421, 5632136521049761902, -8390088894796940536,
|
||||||
|
-193645528485698615, -5979788902190688516, -4907000935050298721, -285522056888777828,
|
||||||
|
-2776431630044341707, 1679342092332374735, 6050638460742422078, -2229851317345194226,
|
||||||
|
-1582494184340482199, 5881353426285907985, 812786550756860885, 4541845584483343330,
|
||||||
|
-6497901820577766722, 4980675660146853729, -4012602956251539747, -329088717864244987,
|
||||||
|
-2896929232104691526, 1495812843684243920, -2153620458055647789, 7370257291860230865,
|
||||||
|
-2466442761497833547, 4706794511633873654, -1398851569026877145, 8549875090542453214,
|
||||||
|
-9189721207376179652, -7894453601103453165, 7297902601803624459, 1011190183918857495,
|
||||||
|
-6985347000036920864, 5147159997473910359, -8326859945294252826, 2659470849286379941,
|
||||||
|
6097729358393448602, -7491646050550022124, -5117116194870963097, -896216826133240300,
|
||||||
|
-745860416168701406, 5803876044675762232, -787954255994554146, -3234519180203704564,
|
||||||
|
-4507534739750823898, -1657200065590290694, 505808562678895611, -4153273856159712438,
|
||||||
|
-8381261370078904295, 572156825025677802, 1791881013492340891, 3393267094866038768,
|
||||||
|
-5444650186382539299, 2352769483186201278, -7930912453007408350, -325464993179687389,
|
||||||
|
-3441562999710612272, -6489413242825283295, 5092019688680754699, -227247482082248967,
|
||||||
|
4234737173186232084, 5027558287275472836, 4635198586344772304, -536033143587636457,
|
||||||
|
5907508150730407386, -8438615781380831356, 972392927514829904, -3801314342046600696,
|
||||||
|
-4064951393885491917, -174840358296132583, 2407211146698877100, -1640089820333676239,
|
||||||
|
3940796514530962282, -5882197405809569433, 3095313889586102949, -1818050141166537098,
|
||||||
|
5832080132947175283, 7890064875145919662, 8184139210799583195, -8073512175445549678,
|
||||||
|
-7758774793014564506, -4581724029666783935, 3516491885471466898, -8267083515063118116,
|
||||||
|
6657089965014657519, 5220884358887979358, 1796677326474620641, 5340761970648932916,
|
||||||
|
1147977171614181568, 5066037465548252321, 2574765911837859848, 1085848279845204775,
|
||||||
|
-5873264506986385449, 6116438694366558490, 2107701075971293812, -7420077970933506541,
|
||||||
|
2469478054175558874, -1855128755834809824, -5431463669011098282, -9038325065738319171,
|
||||||
|
-6966276280341336160, 7217693971077460129, -8314322083775271549, 7196649268545224266,
|
||||||
|
-3585711691453906209, -5267827091426810625, 8057528650917418961, -5084103596553648165,
|
||||||
|
-2601445448341207749, -7850010900052094367, 6527366231383600011, 3507654575162700890,
|
||||||
|
9202058512774729859, 1954818376891585542, -2582991129724600103, 8299563319178235687,
|
||||||
|
-5321504681635821435, 7046310742295574065, -2376176645520785576, -7650733936335907755,
|
||||||
|
8850422670118399721, 3631909142291992901, 5158881091950831288, -6340413719511654215,
|
||||||
|
4763258931815816403, 6280052734341785344, -4979582628649810958, 2043464728020827976,
|
||||||
|
-2678071570832690343, 4562580375758598164, 5495451168795427352, -7485059175264624713,
|
||||||
|
553004618757816492, 6895160632757959823, -989748114590090637, 7139506338801360852,
|
||||||
|
-672480814466784139, 5535668688139305547, 2430933853350256242, -3821430778991574732,
|
||||||
|
-1063731997747047009, -3065878205254005442, 7632066283658143750, 6308328381617103346,
|
||||||
|
3681878764086140361, 3289686137190109749, 6587997200611086848, 244714774258135476,
|
||||||
|
-5143583659437639708, 8090302575944624335, 2945117363431356361, -8359047641006034763,
|
||||||
|
3009039260312620700, -793344576772241777, 401084700045993341, -1968749590416080887,
|
||||||
|
4707864159563588614, -3583123505891281857, -3240864324164777915, -5908273794572565703,
|
||||||
|
-3719524458082857382, -5281400669679581926, 8118566580304798074, 3839261274019871296,
|
||||||
|
7062410411742090847, -8481991033874568140, 6027994129690250817, -6725542042704711878,
|
||||||
|
-2971981702428546974, -7854441788951256975, 8809096399316380241, 6492004350391900708,
|
||||||
|
2462145737463489636, -8818543617934476634, -5070345602623085213, -8961586321599299868,
|
||||||
|
-3758656652254704451, -8630661632476012791, 6764129236657751224, -709716318315418359,
|
||||||
|
-3403028373052861600, -8838073512170985897, -3999237033416576341, -2920240395515973663,
|
||||||
|
-2073249475545404416, 368107899140673753, -6108185202296464250, -6307735683270494757,
|
||||||
|
4782583894627718279, 6718292300699989587, 8387085186914375220, 3387513132024756289,
|
||||||
|
4654329375432538231, -292704475491394206, -3848998599978456535, 7623042350483453954,
|
||||||
|
7725442901813263321, 9186225467561587250, -5132344747257272453, -6865740430362196008,
|
||||||
|
2530936820058611833, 1636551876240043639, -3658707362519810009, 1452244145334316253,
|
||||||
|
-7161729655835084979, -7943791770359481772, 9108481583171221009, -3200093350120725999,
|
||||||
|
5007630032676973346, 2153168792952589781, 6720334534964750538, -3181825545719981703,
|
||||||
|
3433922409283786309, 2285479922797300912, 3110614940896576130, -2856812446131932915,
|
||||||
|
-3804580617188639299, 7163298419643543757, 4891138053923696990, 580618510277907015,
|
||||||
|
1684034065251686769, 4429514767357295841, -8893025458299325803, -8103734041042601133,
|
||||||
|
7177515271653460134, 4589042248470800257, -1530083407795771245, 143607045258444228,
|
||||||
|
246994305896273627, -8356954712051676521, 6473547110565816071, 3092379936208876896,
|
||||||
|
2058427839513754051, -4089587328327907870, 8785882556301281247, -3074039370013608197,
|
||||||
|
-637529855400303673, 6137678347805511274, -7152924852417805802, 5708223427705576541,
|
||||||
|
-3223714144396531304, 4358391411789012426, 325123008708389849, 6837621693887290924,
|
||||||
|
4843721905315627004, -3212720814705499393, -3825019837890901156, 4602025990114250980,
|
||||||
|
1044646352569048800, 9106614159853161675, -8394115921626182539, -4304087667751778808,
|
||||||
|
2681532557646850893, 3681559472488511871, -3915372517896561773, -2889241648411946534,
|
||||||
|
-6564663803938238204, -8060058171802589521, 581945337509520675, 3648778920718647903,
|
||||||
|
-4799698790548231394, -7602572252857820065, 220828013409515943, -1072987336855386047,
|
||||||
|
4287360518296753003, -4633371852008891965, 5513660857261085186, -2258542936462001533,
|
||||||
|
-8744380348503999773, 8746140185685648781, 228500091334420247, 1356187007457302238,
|
||||||
|
3019253992034194581, 3152601605678500003, -8793219284148773595, 5559581553696971176,
|
||||||
|
4916432985369275664, -8559797105120221417, -5802598197927043732, 2868348622579915573,
|
||||||
|
-7224052902810357288, -5894682518218493085, 2587672709781371173, -7706116723325376475,
|
||||||
|
3092343956317362483, -5561119517847711700, 972445599196498113, -1558506600978816441,
|
||||||
|
1708913533482282562, -2305554874185907314, -6005743014309462908, -6653329009633068701,
|
||||||
|
-483583197311151195, 2488075924621352812, -4529369641467339140, -4663743555056261452,
|
||||||
|
2997203966153298104, 1282559373026354493, 240113143146674385, 8665713329246516443,
|
||||||
|
628141331766346752, -4651421219668005332, -7750560848702540400, 7596648026010355826,
|
||||||
|
-3132152619100351065, 7834161864828164065, 7103445518877254909, 4390861237357459201,
|
||||||
|
-4780718172614204074, -319889632007444440, 622261699494173647, -3186110786557562560,
|
||||||
|
-8718967088789066690, -1948156510637662747, -8212195255998774408, -7028621931231314745,
|
||||||
|
2623071828615234808, -4066058308780939700, -5484966924888173764, -6683604512778046238,
|
||||||
|
-6756087640505506466, 5256026990536851868, 7841086888628396109, 6640857538655893162,
|
||||||
|
-8021284697816458310, -7109857044414059830, -1689021141511844405, -4298087301956291063,
|
||||||
|
-4077748265377282003, -998231156719803476, 2719520354384050532, 9132346697815513771,
|
||||||
|
4332154495710163773, -2085582442760428892, 6994721091344268833, -2556143461985726874,
|
||||||
|
-8567931991128098309, 59934747298466858, -3098398008776739403, -265597256199410390,
|
||||||
|
2332206071942466437, -7522315324568406181, 3154897383618636503, -7585605855467168281,
|
||||||
|
-6762850759087199275, 197309393502684135, -8579694182469508493, 2543179307861934850,
|
||||||
|
4350769010207485119, -4468719947444108136, -7207776534213261296, -1224312577878317200,
|
||||||
|
4287946071480840813, 8362686366770308971, 6486469209321732151, -5605644191012979782,
|
||||||
|
-1669018511020473564, 4450022655153542367, -7618176296641240059, -3896357471549267421,
|
||||||
|
-4596796223304447488, -6531150016257070659, -8982326463137525940, -4125325062227681798,
|
||||||
|
-1306489741394045544, -8338554946557245229, 5329160409530630596, 7790979528857726136,
|
||||||
|
4955070238059373407, -4304834761432101506, -6215295852904371179, 3007769226071157901,
|
||||||
|
-6753025801236972788, 8928702772696731736, 7856187920214445904, -4748497451462800923,
|
||||||
|
7900176660600710914, -7082800908938549136, -6797926979589575837, -6737316883512927978,
|
||||||
|
4186670094382025798, 1883939007446035042, -414705992779907823, 3734134241178479257,
|
||||||
|
4065968871360089196, 6953124200385847784, -7917685222115876751, -7585632937840318161,
|
||||||
|
-5567246375906782599, -5256612402221608788, 3106378204088556331, -2894472214076325998,
|
||||||
|
4565385105440252958, 1979884289539493806, -6891578849933910383, 3783206694208922581,
|
||||||
|
8464961209802336085, 2843963751609577687, 3030678195484896323, -4429654462759003204,
|
||||||
|
4459239494808162889, 402587895800087237, 8057891408711167515, 4541888170938985079,
|
||||||
|
1042662272908816815, -3666068979732206850, 2647678726283249984, 2144477441549833761,
|
||||||
|
-3417019821499388721, -2105601033380872185, 5916597177708541638, -8760774321402454447,
|
||||||
|
8833658097025758785, 5970273481425315300, 563813119381731307, -6455022486202078793,
|
||||||
|
1598828206250873866, -4016978389451217698, -2988328551145513985, -6071154634840136312,
|
||||||
|
8469693267274066490, 125672920241807416, -3912292412830714870, -2559617104544284221,
|
||||||
|
-486523741806024092, -4735332261862713930, 5923302823487327109, -9082480245771672572,
|
||||||
|
-1808429243461201518, 7990420780896957397, 4317817392807076702, 3625184369705367340,
|
||||||
|
-6482649271566653105, -3480272027152017464, -3225473396345736649, -368878695502291645,
|
||||||
|
-3981164001421868007, -8522033136963788610, 7609280429197514109, 3020985755112334161,
|
||||||
|
-2572049329799262942, 2635195723621160615, 5144520864246028816, -8188285521126945980,
|
||||||
|
1567242097116389047, 8172389260191636581, -2885551685425483535, -7060359469858316883,
|
||||||
|
-6480181133964513127, -7317004403633452381, 6011544915663598137, 5932255307352610768,
|
||||||
|
2241128460406315459, -8327867140638080220, 3094483003111372717, 4583857460292963101,
|
||||||
|
9079887171656594975, -384082854924064405, -3460631649611717935, 4225072055348026230,
|
||||||
|
-7385151438465742745, 3801620336801580414, -399845416774701952, -7446754431269675473,
|
||||||
|
7899055018877642622, 5421679761463003041, 5521102963086275121, -4975092593295409910,
|
||||||
|
8735487530905098534, -7462844945281082830, -2080886987197029914, -1000715163927557685,
|
||||||
|
-4253840471931071485, -5828896094657903328, 6424174453260338141, 359248545074932887,
|
||||||
|
-5949720754023045210, -2426265837057637212, 3030918217665093212, -9077771202237461772,
|
||||||
|
-3186796180789149575, 740416251634527158, -2142944401404840226, 6951781370868335478,
|
||||||
|
399922722363687927, -8928469722407522623, -1378421100515597285, -8343051178220066766,
|
||||||
|
-3030716356046100229, -8811767350470065420, 9026808440365124461, 6440783557497587732,
|
||||||
|
4615674634722404292, 539897290441580544, 2096238225866883852, 8751955639408182687,
|
||||||
|
-7316147128802486205, 7381039757301768559, 6157238513393239656, -1473377804940618233,
|
||||||
|
8629571604380892756, 5280433031239081479, 7101611890139813254, 2479018537985767835,
|
||||||
|
7169176924412769570, -1281305539061572506, -7865612307799218120, 2278447439451174845,
|
||||||
|
3625338785743880657, 6477479539006708521, 8976185375579272206, -3712000482142939688,
|
||||||
|
1326024180520890843, 7537449876596048829, 5464680203499696154, 3189671183162196045,
|
||||||
|
6346751753565857109, -8982212049534145501, -6127578587196093755, -245039190118465649,
|
||||||
|
-6320577374581628592, 7208698530190629697, 7276901792339343736, -7490986807540332668,
|
||||||
|
4133292154170828382, 2918308698224194548, -7703910638917631350, -3929437324238184044,
|
||||||
|
-4300543082831323144, -6344160503358350167, 5896236396443472108, -758328221503023383,
|
||||||
|
-1894351639983151068, -307900319840287220, -6278469401177312761, -2171292963361310674,
|
||||||
|
8382142935188824023, 9103922860780351547, 4152330101494654406,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type rngSource struct {
|
||||||
|
tap int // index into vec
|
||||||
|
feed int // index into vec
|
||||||
|
vec [rngLen]int64 // current feedback register
|
||||||
|
}
|
||||||
|
|
||||||
|
// seed rng x[n+1] = 48271 * x[n] mod (2**31 - 1)
|
||||||
|
func seedrand(x int32) int32 {
|
||||||
|
const (
|
||||||
|
A = 48271
|
||||||
|
Q = 44488
|
||||||
|
R = 3399
|
||||||
|
)
|
||||||
|
|
||||||
|
hi := x / Q
|
||||||
|
lo := x % Q
|
||||||
|
x = A*lo - R*hi
|
||||||
|
if x < 0 {
|
||||||
|
x += int32max
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seed uses the provided seed value to initialize the generator to a deterministic state.
|
||||||
|
func (rng *rngSource) Seed(seed int64) {
|
||||||
|
rng.tap = 0
|
||||||
|
rng.feed = rngLen - rngTap
|
||||||
|
|
||||||
|
seed = seed % int32max
|
||||||
|
if seed < 0 {
|
||||||
|
seed += int32max
|
||||||
|
}
|
||||||
|
if seed == 0 {
|
||||||
|
seed = 89482311
|
||||||
|
}
|
||||||
|
|
||||||
|
x := int32(seed)
|
||||||
|
for i := -20; i < rngLen; i++ {
|
||||||
|
x = seedrand(x)
|
||||||
|
if i >= 0 {
|
||||||
|
var u int64
|
||||||
|
u = int64(x) << 40
|
||||||
|
x = seedrand(x)
|
||||||
|
u ^= int64(x) << 20
|
||||||
|
x = seedrand(x)
|
||||||
|
u ^= int64(x)
|
||||||
|
u ^= rngCooked[i]
|
||||||
|
rng.vec[i] = u
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int63 returns a non-negative pseudo-random 63-bit integer as an int64.
|
||||||
|
func (rng *rngSource) Int63() int64 {
|
||||||
|
return int64(rng.Uint64() & rngMask)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint64 returns a non-negative pseudo-random 64-bit integer as a uint64.
|
||||||
|
func (rng *rngSource) Uint64() uint64 {
|
||||||
|
rng.tap--
|
||||||
|
if rng.tap < 0 {
|
||||||
|
rng.tap += rngLen
|
||||||
|
}
|
||||||
|
|
||||||
|
rng.feed--
|
||||||
|
if rng.feed < 0 {
|
||||||
|
rng.feed += rngLen
|
||||||
|
}
|
||||||
|
|
||||||
|
x := rng.vec[rng.feed] + rng.vec[rng.tap]
|
||||||
|
rng.vec[rng.feed] = x
|
||||||
|
return uint64(x)
|
||||||
|
}
|
||||||
77
internal/lib/math/rand/zipf.go
Normal file
77
internal/lib/math/rand/zipf.go
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
// W.Hormann, G.Derflinger:
|
||||||
|
// "Rejection-Inversion to Generate Variates
|
||||||
|
// from Monotone Discrete Distributions"
|
||||||
|
// http://eeyore.wu-wien.ac.at/papers/96-04-04.wh-der.ps.gz
|
||||||
|
|
||||||
|
package rand
|
||||||
|
|
||||||
|
import "math"
|
||||||
|
|
||||||
|
// A Zipf generates Zipf distributed variates.
|
||||||
|
type Zipf struct {
|
||||||
|
r *Rand
|
||||||
|
imax float64
|
||||||
|
v float64
|
||||||
|
q float64
|
||||||
|
s float64
|
||||||
|
oneminusQ float64
|
||||||
|
oneminusQinv float64
|
||||||
|
hxm float64
|
||||||
|
hx0minusHxm float64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (z *Zipf) h(x float64) float64 {
|
||||||
|
return math.Exp(z.oneminusQ*math.Log(z.v+x)) * z.oneminusQinv
|
||||||
|
}
|
||||||
|
|
||||||
|
func (z *Zipf) hinv(x float64) float64 {
|
||||||
|
return math.Exp(z.oneminusQinv*math.Log(z.oneminusQ*x)) - z.v
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewZipf returns a Zipf variate generator.
|
||||||
|
// The generator generates values k ∈ [0, imax]
|
||||||
|
// such that P(k) is proportional to (v + k) ** (-s).
|
||||||
|
// Requirements: s > 1 and v >= 1.
|
||||||
|
func NewZipf(r *Rand, s float64, v float64, imax uint64) *Zipf {
|
||||||
|
z := new(Zipf)
|
||||||
|
if s <= 1.0 || v < 1 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
z.r = r
|
||||||
|
z.imax = float64(imax)
|
||||||
|
z.v = v
|
||||||
|
z.q = s
|
||||||
|
z.oneminusQ = 1.0 - z.q
|
||||||
|
z.oneminusQinv = 1.0 / z.oneminusQ
|
||||||
|
z.hxm = z.h(z.imax + 0.5)
|
||||||
|
z.hx0minusHxm = z.h(0.5) - math.Exp(math.Log(z.v)*(-z.q)) - z.hxm
|
||||||
|
z.s = 1 - z.hinv(z.h(1.5)-math.Exp(-z.q*math.Log(z.v+1.0)))
|
||||||
|
return z
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint64 returns a value drawn from the Zipf distribution described
|
||||||
|
// by the Zipf object.
|
||||||
|
func (z *Zipf) Uint64() uint64 {
|
||||||
|
if z == nil {
|
||||||
|
panic("rand: nil Zipf")
|
||||||
|
}
|
||||||
|
k := 0.0
|
||||||
|
|
||||||
|
for {
|
||||||
|
r := z.r.Float64() // r on [0,1]
|
||||||
|
ur := z.hxm + r*z.hx0minusHxm
|
||||||
|
x := z.hinv(ur)
|
||||||
|
k = math.Floor(x + 0.5)
|
||||||
|
if k-x <= z.s {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if ur >= z.h(k+0.5)-math.Exp(-math.Log(k+z.v)*z.q) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return uint64(k)
|
||||||
|
}
|
||||||
@@ -10,7 +10,6 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
/* TODO(xsw):
|
|
||||||
// Expand replaces ${var} or $var in the string based on the mapping function.
|
// Expand replaces ${var} or $var in the string based on the mapping function.
|
||||||
// For example, os.ExpandEnv(s) is equivalent to os.Expand(s, os.Getenv).
|
// For example, os.ExpandEnv(s) is equivalent to os.Expand(s, os.Getenv).
|
||||||
func Expand(s string, mapping func(string) string) string {
|
func Expand(s string, mapping func(string) string) string {
|
||||||
@@ -94,7 +93,6 @@ func getShellName(s string) (string, int) {
|
|||||||
}
|
}
|
||||||
return s[:i], i
|
return s[:i], i
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
// Getenv retrieves the value of the environment variable named by the key.
|
// Getenv retrieves the value of the environment variable named by the key.
|
||||||
// It returns the value, which will be empty if the variable is not present.
|
// It returns the value, which will be empty if the variable is not present.
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/internal/lib/internal/syscall/execenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Error is returned by LookPath when it fails to classify a file as an
|
// Error is returned by LookPath when it fails to classify a file as an
|
||||||
@@ -1089,7 +1091,6 @@ func minInt(a, b int) int {
|
|||||||
// would be run as it is currently configured. If an error occurs in computing
|
// would be run as it is currently configured. If an error occurs in computing
|
||||||
// the environment, it is returned alongside the best-effort copy.
|
// the environment, it is returned alongside the best-effort copy.
|
||||||
func (c *Cmd) environ() ([]string, error) {
|
func (c *Cmd) environ() ([]string, error) {
|
||||||
/* TODO(xsw):
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
env := c.Env
|
env := c.Env
|
||||||
@@ -1128,8 +1129,6 @@ func (c *Cmd) environ() ([]string, error) {
|
|||||||
err = dedupErr
|
err = dedupErr
|
||||||
}
|
}
|
||||||
return addCriticalEnv(env), err
|
return addCriticalEnv(env), err
|
||||||
*/
|
|
||||||
panic("todo: exec.Cmd.environ")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Environ returns a copy of the environment in which the command would be run
|
// Environ returns a copy of the environment in which the command would be run
|
||||||
|
|||||||
@@ -7,8 +7,10 @@
|
|||||||
package os
|
package os
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"runtime"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/internal/lib/internal/itoa"
|
||||||
"github.com/goplus/llgo/internal/lib/internal/syscall/execenv"
|
"github.com/goplus/llgo/internal/lib/internal/syscall/execenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -96,7 +98,6 @@ func (p *ProcessState) sysUsage() any {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *ProcessState) String() string {
|
func (p *ProcessState) String() string {
|
||||||
/* TODO(xsw):
|
|
||||||
if p == nil {
|
if p == nil {
|
||||||
return "<nil>"
|
return "<nil>"
|
||||||
}
|
}
|
||||||
@@ -124,8 +125,6 @@ func (p *ProcessState) String() string {
|
|||||||
res += " (core dumped)"
|
res += " (core dumped)"
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
*/
|
|
||||||
panic("todo: os.ProcessState.String")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExitCode returns the exit code of the exited process, or -1
|
// ExitCode returns the exit code of the exited process, or -1
|
||||||
|
|||||||
@@ -16,13 +16,10 @@ import (
|
|||||||
// be canceled and return immediately with an ErrClosed error.
|
// be canceled and return immediately with an ErrClosed error.
|
||||||
// Close will return an error if it has already been called.
|
// Close will return an error if it has already been called.
|
||||||
func (f *File) Close() error {
|
func (f *File) Close() error {
|
||||||
/*
|
|
||||||
if f == nil {
|
if f == nil {
|
||||||
return ErrInvalid
|
return ErrInvalid
|
||||||
}
|
}
|
||||||
return f.file.close()
|
return f.close()
|
||||||
*/
|
|
||||||
panic("todo: os.(*File).Close")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// pread reads len(b) bytes from the File starting at byte offset off.
|
// pread reads len(b) bytes from the File starting at byte offset off.
|
||||||
|
|||||||
@@ -250,6 +250,27 @@ func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
|
|||||||
return f, nil
|
return f, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (file *File) close() error {
|
||||||
|
return syscall.Close(int(file.fd))
|
||||||
|
/* TODO(xsw):
|
||||||
|
if file.dirinfo != nil {
|
||||||
|
file.dirinfo.close()
|
||||||
|
file.dirinfo = nil
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
if e := file.pfd.Close(); e != nil {
|
||||||
|
if e == poll.ErrFileClosing {
|
||||||
|
e = ErrClosed
|
||||||
|
}
|
||||||
|
err = &PathError{Op: "close", Path: file.name, Err: e}
|
||||||
|
}
|
||||||
|
|
||||||
|
// no need for a finalizer anymore
|
||||||
|
runtime.SetFinalizer(file, nil)
|
||||||
|
return err
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
func tempDir() string {
|
func tempDir() string {
|
||||||
dir := Getenv("TMPDIR")
|
dir := Getenv("TMPDIR")
|
||||||
if dir == "" {
|
if dir == "" {
|
||||||
|
|||||||
@@ -274,9 +274,6 @@ func Mkdir(name string, perm FileMode) error {
|
|||||||
// func MkdirAll(path string, perm FileMode) error
|
// func MkdirAll(path string, perm FileMode) error
|
||||||
// func MkdirTemp(dir, pattern string) (string, error)
|
// func MkdirTemp(dir, pattern string) (string, error)
|
||||||
// func NewSyscallError(syscall string, err error) error
|
// func NewSyscallError(syscall string, err error) error
|
||||||
func Pipe() (r *File, w *File, err error) {
|
|
||||||
panic("todo: os.Pipe")
|
|
||||||
}
|
|
||||||
|
|
||||||
// func ReadFile(name string) ([]byte, error)
|
// func ReadFile(name string) ([]byte, error)
|
||||||
|
|
||||||
|
|||||||
22
internal/lib/os/pipe2_unix.go
Normal file
22
internal/lib/os/pipe2_unix.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
// Copyright 2017 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.
|
||||||
|
|
||||||
|
//go:build dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
||||||
|
|
||||||
|
package os
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
// Pipe returns a connected pair of Files; reads from r return bytes written to w.
|
||||||
|
// It returns the files and an error, if any.
|
||||||
|
func Pipe() (r *File, w *File, err error) {
|
||||||
|
var p [2]int
|
||||||
|
|
||||||
|
e := syscall.Pipe2(p[0:], syscall.O_CLOEXEC)
|
||||||
|
if e != nil {
|
||||||
|
return nil, nil, NewSyscallError("pipe2", e)
|
||||||
|
}
|
||||||
|
|
||||||
|
return newFile(p[0], "|0", kindPipe), newFile(p[1], "|1", kindPipe), nil
|
||||||
|
}
|
||||||
28
internal/lib/os/pipe_unix.go
Normal file
28
internal/lib/os/pipe_unix.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
//go:build aix || darwin
|
||||||
|
|
||||||
|
package os
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
// Pipe returns a connected pair of Files; reads from r return bytes written to w.
|
||||||
|
// It returns the files and an error, if any.
|
||||||
|
func Pipe() (r *File, w *File, err error) {
|
||||||
|
var p [2]int
|
||||||
|
|
||||||
|
// See ../syscall/exec.go for description of lock.
|
||||||
|
syscall.ForkLock.RLock()
|
||||||
|
e := syscall.Pipe(p[0:])
|
||||||
|
if e != nil {
|
||||||
|
syscall.ForkLock.RUnlock()
|
||||||
|
return nil, nil, NewSyscallError("pipe", e)
|
||||||
|
}
|
||||||
|
syscall.CloseOnExec(p[0])
|
||||||
|
syscall.CloseOnExec(p[1])
|
||||||
|
syscall.ForkLock.RUnlock()
|
||||||
|
|
||||||
|
return newFile(p[0], "|0", kindPipe), newFile(p[1], "|1", kindPipe), nil
|
||||||
|
}
|
||||||
16
internal/lib/os/pipe_wasm.go
Normal file
16
internal/lib/os/pipe_wasm.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// Copyright 2023 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.
|
||||||
|
|
||||||
|
//go:build wasm
|
||||||
|
|
||||||
|
package os
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
// Pipe returns a connected pair of Files; reads from r return bytes written to w.
|
||||||
|
// It returns the files and an error, if any.
|
||||||
|
func Pipe() (r *File, w *File, err error) {
|
||||||
|
// Neither GOOS=js nor GOOS=wasip1 have pipes.
|
||||||
|
return nil, nil, NewSyscallError("pipe", syscall.ENOSYS)
|
||||||
|
}
|
||||||
@@ -5,8 +5,9 @@
|
|||||||
package os
|
package os
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"syscall"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c/syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
func fillFileStatFromSys(fs *fileStat, name string) {
|
func fillFileStatFromSys(fs *fileStat, name string) {
|
||||||
|
|||||||
@@ -6,12 +6,15 @@
|
|||||||
|
|
||||||
package os
|
package os
|
||||||
|
|
||||||
import "syscall"
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/os"
|
||||||
|
"github.com/goplus/llgo/internal/lib/syscall"
|
||||||
|
)
|
||||||
|
|
||||||
// Stat returns the FileInfo structure describing file.
|
// Stat returns the FileInfo structure describing file.
|
||||||
// If there is an error, it will be of type *PathError.
|
// If there is an error, it will be of type *PathError.
|
||||||
func (f *File) Stat() (FileInfo, error) {
|
func (f *File) Stat() (FileInfo, error) {
|
||||||
/* TODO(xsw):
|
|
||||||
if f == nil {
|
if f == nil {
|
||||||
return nil, ErrInvalid
|
return nil, ErrInvalid
|
||||||
}
|
}
|
||||||
@@ -22,8 +25,6 @@ func (f *File) Stat() (FileInfo, error) {
|
|||||||
}
|
}
|
||||||
fillFileStatFromSys(&fs, f.name)
|
fillFileStatFromSys(&fs, f.name)
|
||||||
return &fs, nil
|
return &fs, nil
|
||||||
*/
|
|
||||||
panic("todo: os.File.Stat")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// statNolog stats a file with no test logging.
|
// statNolog stats a file with no test logging.
|
||||||
|
|||||||
39
internal/lib/os/str.go
Normal file
39
internal/lib/os/str.go
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
// Simple conversions to avoid depending on strconv.
|
||||||
|
|
||||||
|
package os
|
||||||
|
|
||||||
|
// itox converts val (an int) to a hexadecimal string.
|
||||||
|
func itox(val int) string {
|
||||||
|
if val < 0 {
|
||||||
|
return "-" + uitox(uint(-val))
|
||||||
|
}
|
||||||
|
return uitox(uint(val))
|
||||||
|
}
|
||||||
|
|
||||||
|
const hex = "0123456789abcdef"
|
||||||
|
|
||||||
|
// uitox converts val (a uint) to a hexadecimal string.
|
||||||
|
func uitox(val uint) string {
|
||||||
|
if val == 0 { // avoid string allocation
|
||||||
|
return "0x0"
|
||||||
|
}
|
||||||
|
var buf [20]byte // big enough for 64bit value base 16 + 0x
|
||||||
|
i := len(buf) - 1
|
||||||
|
for val >= 16 {
|
||||||
|
q := val / 16
|
||||||
|
buf[i] = hex[val%16]
|
||||||
|
i--
|
||||||
|
val = q
|
||||||
|
}
|
||||||
|
// val < 16
|
||||||
|
buf[i] = hex[val%16]
|
||||||
|
i--
|
||||||
|
buf[i] = 'x'
|
||||||
|
i--
|
||||||
|
buf[i] = '0'
|
||||||
|
return string(buf[i:])
|
||||||
|
}
|
||||||
@@ -7,8 +7,9 @@
|
|||||||
package os
|
package os
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"syscall"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/internal/lib/syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A fileStat is the implementation of FileInfo returned by Stat and Lstat.
|
// A fileStat is the implementation of FileInfo returned by Stat and Lstat.
|
||||||
|
|||||||
@@ -1579,8 +1579,10 @@ func (v Value) CanUint() bool {
|
|||||||
// Uint returns v's underlying value, as a uint64.
|
// Uint returns v's underlying value, as a uint64.
|
||||||
// It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64.
|
// It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64.
|
||||||
func (v Value) Uint() uint64 {
|
func (v Value) Uint() uint64 {
|
||||||
|
f := v.flag
|
||||||
k := v.kind()
|
k := v.kind()
|
||||||
p := v.ptr
|
p := v.ptr
|
||||||
|
if f&flagAddr != 0 {
|
||||||
switch k {
|
switch k {
|
||||||
case Uint:
|
case Uint:
|
||||||
return uint64(*(*uint)(p))
|
return uint64(*(*uint)(p))
|
||||||
@@ -1595,10 +1597,21 @@ func (v Value) Uint() uint64 {
|
|||||||
case Uintptr:
|
case Uintptr:
|
||||||
return uint64(*(*uintptr)(p))
|
return uint64(*(*uintptr)(p))
|
||||||
}
|
}
|
||||||
|
} else if unsafe.Sizeof(uintptr(0)) == 8 {
|
||||||
|
if k >= Uint && k <= Uintptr {
|
||||||
|
return uint64(uintptr(p))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if k >= Uint && k <= Uint32 {
|
||||||
|
return uint64(uintptr(p))
|
||||||
|
}
|
||||||
|
if k == Uint64 || k == Uintptr {
|
||||||
|
return *(*uint64)(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
panic(&ValueError{"reflect.Value.Uint", v.kind()})
|
panic(&ValueError{"reflect.Value.Uint", v.kind()})
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:nocheckptr
|
|
||||||
// This prevents inlining Value.UnsafeAddr when -d=checkptr is enabled,
|
// This prevents inlining Value.UnsafeAddr when -d=checkptr is enabled,
|
||||||
// which ensures cmd/compile can recognize unsafe.Pointer(v.UnsafeAddr())
|
// which ensures cmd/compile can recognize unsafe.Pointer(v.UnsafeAddr())
|
||||||
// and make an exception.
|
// and make an exception.
|
||||||
|
|||||||
@@ -24,6 +24,10 @@ type Pool struct {
|
|||||||
func (p *Pool) Put(x any) {
|
func (p *Pool) Put(x any) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(xsw):
|
||||||
func (p *Pool) Get() any {
|
func (p *Pool) Get() any {
|
||||||
|
if p.New != nil {
|
||||||
return p.New()
|
return p.New()
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
package syscall
|
package syscall
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"github.com/goplus/llgo/c"
|
"github.com/goplus/llgo/c"
|
||||||
"github.com/goplus/llgo/c/os"
|
"github.com/goplus/llgo/c/os"
|
||||||
"github.com/goplus/llgo/c/syscall"
|
"github.com/goplus/llgo/c/syscall"
|
||||||
@@ -261,22 +263,17 @@ func forkAndExecInChild(argv0 *c.Char, argv, envv **c.Char, chroot, dir *c.Char,
|
|||||||
if fd[i] == i {
|
if fd[i] == i {
|
||||||
// dup2(i, i) won't clear close-on-exec flag on Linux,
|
// dup2(i, i) won't clear close-on-exec flag on Linux,
|
||||||
// probably not elsewhere either.
|
// probably not elsewhere either.
|
||||||
ret := os.Fcntl(c.Int(fd[i]), syscall.F_SETFD, 0)
|
if ret := os.Fcntl(c.Int(fd[i]), syscall.F_SETFD, 0); ret < 0 {
|
||||||
if ret != 0 {
|
err1 = Errno(os.Errno)
|
||||||
err1 = Errno(ret)
|
|
||||||
goto childerror
|
goto childerror
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
/* TODO(xsw):
|
|
||||||
// The new fd is created NOT close-on-exec,
|
// The new fd is created NOT close-on-exec,
|
||||||
// which is exactly what we want.
|
if ret := os.Dup2(c.Int(fd[i]), c.Int(i)); ret < 0 {
|
||||||
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_dup2_trampoline), uintptr(fd[i]), uintptr(i), 0)
|
err1 = Errno(os.Errno)
|
||||||
if err1 != 0 {
|
|
||||||
goto childerror
|
goto childerror
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
panic("todo: syscall.forkAndExecInChild - dup2")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// By convention, we don't close-on-exec the fds we are
|
// By convention, we don't close-on-exec the fds we are
|
||||||
@@ -284,10 +281,7 @@ func forkAndExecInChild(argv0 *c.Char, argv, envv **c.Char, chroot, dir *c.Char,
|
|||||||
// Programs that know they inherit fds >= 3 will need
|
// Programs that know they inherit fds >= 3 will need
|
||||||
// to set them close-on-exec.
|
// to set them close-on-exec.
|
||||||
for i = len(fd); i < 3; i++ {
|
for i = len(fd); i < 3; i++ {
|
||||||
/* TODO(xsw):
|
os.Close(c.Int(i))
|
||||||
rawSyscall(abi.FuncPCABI0(libc_close_trampoline), uintptr(i), 0, 0)
|
|
||||||
*/
|
|
||||||
panic("todo: syscall.forkAndExecInChild - for i")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detach fd 0 from tty
|
// Detach fd 0 from tty
|
||||||
@@ -327,12 +321,9 @@ func forkAndExecInChild(argv0 *c.Char, argv, envv **c.Char, chroot, dir *c.Char,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
childerror:
|
childerror:
|
||||||
/* TODO(xsw):
|
|
||||||
// send error code on pipe
|
// send error code on pipe
|
||||||
rawSyscall(abi.FuncPCABI0(libc_write_trampoline), uintptr(pipe), uintptr(unsafe.Pointer(&err1)), unsafe.Sizeof(err1))
|
os.Write(c.Int(pipe), unsafe.Pointer(&err1), unsafe.Sizeof(err1))
|
||||||
for {
|
for {
|
||||||
rawSyscall(abi.FuncPCABI0(libc_exit_trampoline), 253, 0, 0)
|
os.Exit(253)
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
panic("todo: syscall.forkAndExecInChild - childerror")
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,10 +68,7 @@ import (
|
|||||||
var ForkLock sync.RWMutex
|
var ForkLock sync.RWMutex
|
||||||
|
|
||||||
func CloseOnExec(fd int) {
|
func CloseOnExec(fd int) {
|
||||||
/* TODO(xsw):
|
os.Fcntl(c.Int(fd), syscall.F_SETFD, syscall.FD_CLOEXEC)
|
||||||
fcntl(fd, F_SETFD, FD_CLOEXEC)
|
|
||||||
*/
|
|
||||||
panic("todo: syscall.CloseOnExec")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetNonblock(fd int, nonblocking bool) (err error) {
|
func SetNonblock(fd int, nonblocking bool) (err error) {
|
||||||
|
|||||||
@@ -239,6 +239,12 @@ func (p *selectOp) init() {
|
|||||||
p.sem = false
|
p.sem = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *selectOp) end() {
|
||||||
|
p.mutex.Destroy()
|
||||||
|
p.cond.Destroy()
|
||||||
|
p.next = nil
|
||||||
|
}
|
||||||
|
|
||||||
func (p *selectOp) notify() {
|
func (p *selectOp) notify() {
|
||||||
p.mutex.Lock()
|
p.mutex.Lock()
|
||||||
p.sem = true
|
p.sem = true
|
||||||
@@ -299,6 +305,7 @@ func Select(ops ...ChanOp) (isel int, recvOK bool) {
|
|||||||
for _, op := range ops {
|
for _, op := range ops {
|
||||||
endSelect(op.C, selOp)
|
endSelect(op.C, selOp)
|
||||||
}
|
}
|
||||||
|
selOp.end()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,7 +324,6 @@ func endSelect(c *Chan, selOp *selectOp) {
|
|||||||
}
|
}
|
||||||
*pp = selOp.next
|
*pp = selOp.next
|
||||||
c.mutex.Unlock()
|
c.mutex.Unlock()
|
||||||
selOp.next = nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -96,6 +96,10 @@ func printany(i any) {
|
|||||||
print(v)
|
print(v)
|
||||||
case string:
|
case string:
|
||||||
print(v)
|
print(v)
|
||||||
|
case error:
|
||||||
|
print(v.Error())
|
||||||
|
case interface{ String() string }:
|
||||||
|
print(v.String())
|
||||||
default:
|
default:
|
||||||
printanycustomtype(i)
|
printanycustomtype(i)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ type Defer struct {
|
|||||||
Addr unsafe.Pointer // sigjmpbuf
|
Addr unsafe.Pointer // sigjmpbuf
|
||||||
Bits uintptr
|
Bits uintptr
|
||||||
Link *Defer
|
Link *Defer
|
||||||
|
Reth unsafe.Pointer // block address after Rethrow
|
||||||
Rund unsafe.Pointer // block address after RunDefers
|
Rund unsafe.Pointer // block address after RunDefers
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,12 +47,6 @@ func Recover() (ret any) {
|
|||||||
|
|
||||||
// Panic panics with a value.
|
// Panic panics with a value.
|
||||||
func Panic(v any) {
|
func Panic(v any) {
|
||||||
switch e := v.(type) {
|
|
||||||
case error:
|
|
||||||
v = e.Error()
|
|
||||||
case interface{ String() string }:
|
|
||||||
v = e.String()
|
|
||||||
}
|
|
||||||
ptr := c.Malloc(unsafe.Sizeof(v))
|
ptr := c.Malloc(unsafe.Sizeof(v))
|
||||||
*(*any)(ptr) = v
|
*(*any)(ptr) = v
|
||||||
excepKey.Set(ptr)
|
excepKey.Set(ptr)
|
||||||
@@ -82,10 +77,6 @@ func init() {
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
func unpackEface(i any) *eface {
|
|
||||||
return (*eface)(unsafe.Pointer(&i))
|
|
||||||
}
|
|
||||||
|
|
||||||
// TracePanic prints panic message.
|
// TracePanic prints panic message.
|
||||||
func TracePanic(v any) {
|
func TracePanic(v any) {
|
||||||
print("panic: ")
|
print("panic: ")
|
||||||
|
|||||||
18
py/dict.go
18
py/dict.go
@@ -42,4 +42,22 @@ func (d *Object) DictValues() *Object { return nil }
|
|||||||
// llgo:link (*Object).DictItems C.PyDict_Items
|
// llgo:link (*Object).DictItems C.PyDict_Items
|
||||||
func (d *Object) DictItems() *Object { return nil }
|
func (d *Object) DictItems() *Object { return nil }
|
||||||
|
|
||||||
|
// Insert val into the dictionary d with a key of key. key must be hashable;
|
||||||
|
// if it isn’t, return -1 and TypeError will be set. Return 0 on success or
|
||||||
|
// -1 on failure.
|
||||||
|
//
|
||||||
|
// llgo:link (*Object).DictSetItem C.PyDict_SetItem
|
||||||
|
func (d *Object) DictSetItem(key *Object, val *Object) *Object { return nil }
|
||||||
|
|
||||||
|
// Return the object from dictionary d which has a key key. Return nil if the
|
||||||
|
// key key is not present, but without setting an exception.
|
||||||
|
//
|
||||||
|
// llgo:link (*Object).DictGetItem C.PyDict_GetItem
|
||||||
|
func (d *Object) DictGetItem(key *Object) *Object { return nil }
|
||||||
|
|
||||||
|
// Return the number of items in the dictionary.
|
||||||
|
//
|
||||||
|
// llgo:link (*Object).DictSize C.PyDict_Size
|
||||||
|
func (d *Object) DictSize() uintptr { return 0 }
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
98
ssa/eh.go
98
ssa/eh.go
@@ -63,7 +63,11 @@ func (b Builder) AllocaSigjmpBuf() Expr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b Builder) Sigsetjmp(jb, savemask Expr) Expr {
|
func (b Builder) Sigsetjmp(jb, savemask Expr) Expr {
|
||||||
fn := b.Pkg.cFunc("sigsetjmp", b.Prog.tySigsetjmp())
|
fname := "sigsetjmp"
|
||||||
|
if b.Prog.target.GOOS == "linux" {
|
||||||
|
fname = "__sigsetjmp"
|
||||||
|
}
|
||||||
|
fn := b.Pkg.cFunc(fname, b.Prog.tySigsetjmp())
|
||||||
return b.Call(fn, jb, savemask)
|
return b.Call(fn, jb, savemask)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,9 +94,11 @@ type aDefer struct {
|
|||||||
key Expr // pthread TLS key
|
key Expr // pthread TLS key
|
||||||
data Expr // pointer to runtime.Defer
|
data Expr // pointer to runtime.Defer
|
||||||
bitsPtr Expr // pointer to defer bits
|
bitsPtr Expr // pointer to defer bits
|
||||||
rundPtr Expr // pointer to RunDefers index
|
rethPtr Expr // next block of Rethrow
|
||||||
|
rundPtr Expr // next block of RunDefers
|
||||||
procBlk BasicBlock // deferProc block
|
procBlk BasicBlock // deferProc block
|
||||||
runsNext []BasicBlock // next blocks of RunDefers
|
panicBlk BasicBlock // panic block (runDefers and rethrow)
|
||||||
|
rundsNext []BasicBlock // next blocks of RunDefers
|
||||||
stmts []func(bits Expr)
|
stmts []func(bits Expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,53 +130,59 @@ const (
|
|||||||
// 0: addr sigjmpbuf
|
// 0: addr sigjmpbuf
|
||||||
// 1: bits uintptr
|
// 1: bits uintptr
|
||||||
// 2: link *Defer
|
// 2: link *Defer
|
||||||
// 3: rund voidptr
|
// 3: reth voidptr: block address after Rethrow
|
||||||
|
// 4: rund voidptr: block address after RunDefers
|
||||||
deferSigjmpbuf = iota
|
deferSigjmpbuf = iota
|
||||||
deferBits
|
deferBits
|
||||||
deferLink
|
deferLink
|
||||||
deferRund
|
deferRethrow
|
||||||
|
deferRunDefers
|
||||||
)
|
)
|
||||||
|
|
||||||
func (b Builder) getDefer(kind DoAction) *aDefer {
|
func (b Builder) getDefer(kind DoAction) *aDefer {
|
||||||
self := b.Func
|
self := b.Func
|
||||||
if self.defer_ == nil {
|
if self.defer_ == nil {
|
||||||
// TODO(xsw): check if in pkg.init
|
// TODO(xsw): check if in pkg.init
|
||||||
var next, rundBlk BasicBlock
|
var next, panicBlk BasicBlock
|
||||||
if kind != DeferAlways {
|
if kind != DeferAlways {
|
||||||
b, next = self.deferInitBuilder()
|
b, next = self.deferInitBuilder()
|
||||||
}
|
}
|
||||||
|
|
||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
|
blks := self.MakeBlocks(2)
|
||||||
|
procBlk, rethrowBlk := blks[0], blks[1]
|
||||||
|
|
||||||
key := b.deferKey()
|
key := b.deferKey()
|
||||||
zero := prog.Val(uintptr(0))
|
zero := prog.Val(uintptr(0))
|
||||||
link := Expr{b.pthreadGetspecific(key).impl, prog.DeferPtr()}
|
link := Expr{b.pthreadGetspecific(key).impl, prog.DeferPtr()}
|
||||||
jb := b.AllocaSigjmpBuf()
|
jb := b.AllocaSigjmpBuf()
|
||||||
ptr := b.aggregateAlloca(prog.Defer(), jb.impl, zero.impl, link.impl)
|
ptr := b.aggregateAlloca(prog.Defer(), jb.impl, zero.impl, link.impl, procBlk.Addr().impl)
|
||||||
deferData := Expr{ptr, prog.DeferPtr()}
|
deferData := Expr{ptr, prog.DeferPtr()}
|
||||||
b.pthreadSetspecific(key, deferData)
|
b.pthreadSetspecific(key, deferData)
|
||||||
blks := self.MakeBlocks(2)
|
|
||||||
procBlk, rethrowBlk := blks[0], blks[1]
|
|
||||||
bitsPtr := b.FieldAddr(deferData, deferBits)
|
bitsPtr := b.FieldAddr(deferData, deferBits)
|
||||||
rundPtr := b.FieldAddr(deferData, deferRund)
|
rethPtr := b.FieldAddr(deferData, deferRethrow)
|
||||||
|
rundPtr := b.FieldAddr(deferData, deferRunDefers)
|
||||||
|
|
||||||
|
czero := prog.IntVal(0, prog.CInt())
|
||||||
|
retval := b.Sigsetjmp(jb, czero)
|
||||||
|
if kind != DeferAlways {
|
||||||
|
panicBlk = self.MakeBlock()
|
||||||
|
} else {
|
||||||
|
blks = self.MakeBlocks(2)
|
||||||
|
next, panicBlk = blks[0], blks[1]
|
||||||
|
}
|
||||||
|
b.If(b.BinOp(token.EQL, retval, czero), next, panicBlk)
|
||||||
|
|
||||||
self.defer_ = &aDefer{
|
self.defer_ = &aDefer{
|
||||||
key: key,
|
key: key,
|
||||||
data: deferData,
|
data: deferData,
|
||||||
bitsPtr: bitsPtr,
|
bitsPtr: bitsPtr,
|
||||||
|
rethPtr: rethPtr,
|
||||||
rundPtr: rundPtr,
|
rundPtr: rundPtr,
|
||||||
procBlk: procBlk,
|
procBlk: procBlk,
|
||||||
runsNext: []BasicBlock{rethrowBlk},
|
panicBlk: panicBlk,
|
||||||
|
rundsNext: []BasicBlock{rethrowBlk},
|
||||||
}
|
}
|
||||||
czero := prog.IntVal(0, prog.CInt())
|
|
||||||
retval := b.Sigsetjmp(jb, czero)
|
|
||||||
if kind != DeferAlways {
|
|
||||||
rundBlk = self.MakeBlock()
|
|
||||||
} else {
|
|
||||||
blks = self.MakeBlocks(2)
|
|
||||||
next, rundBlk = blks[0], blks[1]
|
|
||||||
}
|
|
||||||
b.If(b.BinOp(token.EQL, retval, czero), next, rundBlk)
|
|
||||||
b.SetBlockEx(rundBlk, AtEnd, false) // exec runDefers and rethrow
|
|
||||||
b.Store(rundPtr, rethrowBlk.Addr())
|
|
||||||
b.Jump(procBlk)
|
|
||||||
|
|
||||||
b.SetBlockEx(rethrowBlk, AtEnd, false) // rethrow
|
b.SetBlockEx(rethrowBlk, AtEnd, false) // rethrow
|
||||||
b.Call(b.Pkg.rtFunc("Rethrow"), link)
|
b.Call(b.Pkg.rtFunc("Rethrow"), link)
|
||||||
@@ -229,7 +241,7 @@ func (b Builder) Defer(kind DoAction, fn Expr, args ...Expr) {
|
|||||||
func (b Builder) RunDefers() {
|
func (b Builder) RunDefers() {
|
||||||
self := b.getDefer(DeferInCond)
|
self := b.getDefer(DeferInCond)
|
||||||
blk := b.Func.MakeBlock()
|
blk := b.Func.MakeBlock()
|
||||||
self.runsNext = append(self.runsNext, blk)
|
self.rundsNext = append(self.rundsNext, blk)
|
||||||
|
|
||||||
b.Store(self.rundPtr, blk.Addr())
|
b.Store(self.rundPtr, blk.Addr())
|
||||||
b.Jump(self.procBlk)
|
b.Jump(self.procBlk)
|
||||||
@@ -243,20 +255,42 @@ func (p Function) endDefer(b Builder) {
|
|||||||
if self == nil {
|
if self == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
nexts := self.runsNext
|
nexts := self.rundsNext
|
||||||
if len(nexts) == 0 {
|
if len(nexts) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
b.SetBlockEx(self.procBlk, AtEnd, true)
|
|
||||||
bits := b.Load(self.bitsPtr)
|
|
||||||
stmts := self.stmts
|
|
||||||
for i := len(stmts) - 1; i >= 0; i-- {
|
|
||||||
stmts[i](bits)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
rethrowBlk := nexts[0]
|
||||||
|
procBlk := self.procBlk
|
||||||
|
panicBlk := self.panicBlk
|
||||||
|
rethPtr := self.rethPtr
|
||||||
|
rundPtr := self.rundPtr
|
||||||
|
bitsPtr := self.bitsPtr
|
||||||
|
|
||||||
|
stmts := self.stmts
|
||||||
|
n := len(stmts)
|
||||||
|
rethsNext := make([]BasicBlock, n+1)
|
||||||
|
blks := p.MakeBlocks(n - 1)
|
||||||
|
copy(rethsNext[1:], blks)
|
||||||
|
rethsNext[0] = rethrowBlk
|
||||||
|
rethsNext[n] = procBlk
|
||||||
|
|
||||||
|
for i := n - 1; i >= 0; i-- {
|
||||||
|
rethNext := rethsNext[i]
|
||||||
|
b.SetBlockEx(rethsNext[i+1], AtEnd, true)
|
||||||
|
b.Store(rethPtr, rethNext.Addr())
|
||||||
|
stmts[i](b.Load(bitsPtr))
|
||||||
|
if i != 0 {
|
||||||
|
b.Jump(rethNext)
|
||||||
|
}
|
||||||
|
}
|
||||||
link := b.getField(b.Load(self.data), deferLink)
|
link := b.getField(b.Load(self.data), deferLink)
|
||||||
b.pthreadSetspecific(self.key, link)
|
b.pthreadSetspecific(self.key, link)
|
||||||
b.IndirectJump(b.Load(self.rundPtr), nexts)
|
b.IndirectJump(b.Load(rundPtr), nexts)
|
||||||
|
|
||||||
|
b.SetBlockEx(panicBlk, AtEnd, false) // panicBlk: exec runDefers and rethrow
|
||||||
|
b.Store(rundPtr, rethrowBlk.Addr())
|
||||||
|
b.IndirectJump(b.Load(rethPtr), rethsNext)
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
61
ssa/expr.go
61
ssa/expr.go
@@ -383,7 +383,7 @@ var boolPredOpToLLVM = []llvm.IntPredicate{
|
|||||||
token.NEQ - predOpBase: llvm.IntNE,
|
token.NEQ - predOpBase: llvm.IntNE,
|
||||||
}
|
}
|
||||||
|
|
||||||
// EQL NEQ LSS LEQ GTR GEQ == != < <= < >=
|
// EQL NEQ LSS LEQ GTR GEQ == != < <= > >=
|
||||||
func isPredOp(op token.Token) bool {
|
func isPredOp(op token.Token) bool {
|
||||||
return op >= predOpBase && op <= predOpLast
|
return op >= predOpBase && op <= predOpLast
|
||||||
}
|
}
|
||||||
@@ -392,7 +392,7 @@ func isPredOp(op token.Token) bool {
|
|||||||
// op can be:
|
// op can be:
|
||||||
// ADD SUB MUL QUO REM + - * / %
|
// ADD SUB MUL QUO REM + - * / %
|
||||||
// AND OR XOR SHL SHR AND_NOT & | ^ << >> &^
|
// AND OR XOR SHL SHR AND_NOT & | ^ << >> &^
|
||||||
// EQL NEQ LSS LEQ GTR GEQ == != < <= < >=
|
// EQL NEQ LSS LEQ GTR GEQ == != < <= > >=
|
||||||
func (b Builder) BinOp(op token.Token, x, y Expr) Expr {
|
func (b Builder) BinOp(op token.Token, x, y Expr) Expr {
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("BinOp %d, %v, %v\n", op, x.impl, y.impl)
|
log.Printf("BinOp %d, %v, %v\n", op, x.impl, y.impl)
|
||||||
@@ -490,7 +490,7 @@ func (b Builder) BinOp(op token.Token, x, y Expr) Expr {
|
|||||||
llop := logicOpToLLVM[op-logicOpBase]
|
llop := logicOpToLLVM[op-logicOpBase]
|
||||||
return Expr{llvm.CreateBinOp(b.impl, llop, x.impl, y.impl), x.Type}
|
return Expr{llvm.CreateBinOp(b.impl, llop, x.impl, y.impl), x.Type}
|
||||||
}
|
}
|
||||||
case isPredOp(op): // op: == != < <= < >=
|
case isPredOp(op): // op: == != < <= > >=
|
||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
tret := prog.Bool()
|
tret := prog.Bool()
|
||||||
kind := x.kind
|
kind := x.kind
|
||||||
@@ -562,7 +562,7 @@ func (b Builder) BinOp(op token.Token, x, y Expr) Expr {
|
|||||||
return Expr{llvm.CreateICmp(b.impl, pred, x.impl, y.impl), tret}
|
return Expr{llvm.CreateICmp(b.impl, pred, x.impl, y.impl), tret}
|
||||||
}
|
}
|
||||||
case vkArray:
|
case vkArray:
|
||||||
typ := x.raw.Type.(*types.Array)
|
typ := x.raw.Type.Underlying().(*types.Array)
|
||||||
elem := b.Prog.Elem(x.Type)
|
elem := b.Prog.Elem(x.Type)
|
||||||
ret := prog.BoolVal(true)
|
ret := prog.BoolVal(true)
|
||||||
for i, n := 0, int(typ.Len()); i < n; i++ {
|
for i, n := 0, int(typ.Len()); i < n; i++ {
|
||||||
@@ -694,8 +694,31 @@ func (b Builder) ChangeType(t Type, x Expr) (ret Expr) {
|
|||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("ChangeType %v, %v\n", t.RawType(), x.impl)
|
log.Printf("ChangeType %v, %v\n", t.RawType(), x.impl)
|
||||||
}
|
}
|
||||||
if t.kind == vkClosure && x.kind == vkFuncDecl {
|
if t.kind == vkClosure {
|
||||||
ret.impl = checkExpr(x, t.raw.Type.Underlying(), b).impl
|
switch x.kind {
|
||||||
|
case vkFuncDecl:
|
||||||
|
ret.impl = checkExpr(x, t.raw.Type, b).impl
|
||||||
|
case vkClosure:
|
||||||
|
// TODO(xsw): change type should be a noop instruction
|
||||||
|
convType := func() Expr {
|
||||||
|
r := Expr{llvm.CreateAlloca(b.impl, t.ll), b.Prog.Pointer(t)}
|
||||||
|
b.Store(r, x)
|
||||||
|
return b.Load(r)
|
||||||
|
}
|
||||||
|
switch t.RawType().(type) {
|
||||||
|
case *types.Named:
|
||||||
|
if _, ok := x.RawType().(*types.Struct); ok {
|
||||||
|
return convType()
|
||||||
|
}
|
||||||
|
case *types.Struct:
|
||||||
|
if _, ok := x.RawType().(*types.Named); ok {
|
||||||
|
return convType()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fallthrough
|
||||||
|
default:
|
||||||
|
ret.impl = x.impl
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ret.impl = x.impl
|
ret.impl = x.impl
|
||||||
}
|
}
|
||||||
@@ -991,6 +1014,22 @@ func (b Builder) Do(da DoAction, fn Expr, args ...Expr) (ret Expr) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// compareSelect performs a series of comparisons and selections based on the
|
||||||
|
// given comparison op. It's used to implement operations like min and max.
|
||||||
|
//
|
||||||
|
// The function iterates through the provided expressions, comparing each with
|
||||||
|
// the current result using the specified comparison op. It selects the
|
||||||
|
// appropriate value based on the comparison.
|
||||||
|
func (b Builder) compareSelect(op token.Token, x Expr, y ...Expr) Expr {
|
||||||
|
ret := x
|
||||||
|
for _, v := range y {
|
||||||
|
cond := b.BinOp(op, ret, v)
|
||||||
|
sel := llvm.CreateSelect(b.impl, cond.impl, ret.impl, v.impl)
|
||||||
|
ret = Expr{sel, ret.Type}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
// A Builtin represents a specific use of a built-in function, e.g. len.
|
// A Builtin represents a specific use of a built-in function, e.g. len.
|
||||||
//
|
//
|
||||||
// Builtins are immutable values. Builtins do not have addresses.
|
// Builtins are immutable values. Builtins do not have addresses.
|
||||||
@@ -1101,6 +1140,14 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) {
|
|||||||
b.Call(b.Pkg.rtFunc("MapClear"), t, m)
|
b.Call(b.Pkg.rtFunc("MapClear"), t, m)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
case "min":
|
||||||
|
if len(args) > 0 {
|
||||||
|
return b.compareSelect(token.LSS, args[0], args[1:]...)
|
||||||
|
}
|
||||||
|
case "max":
|
||||||
|
if len(args) > 0 {
|
||||||
|
return b.compareSelect(token.GTR, args[0], args[1:]...)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
panic("todo: " + fn)
|
panic("todo: " + fn)
|
||||||
}
|
}
|
||||||
@@ -1172,7 +1219,7 @@ func (b Builder) PrintEx(ln bool, args ...Expr) (ret Expr) {
|
|||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
func checkExpr(v Expr, t types.Type, b Builder) Expr {
|
func checkExpr(v Expr, t types.Type, b Builder) Expr {
|
||||||
if t, ok := t.(*types.Struct); ok && isClosure(t) {
|
if st, ok := t.Underlying().(*types.Struct); ok && isClosure(st) {
|
||||||
if v.kind != vkClosure {
|
if v.kind != vkClosure {
|
||||||
return b.Pkg.closureStub(b, t, v)
|
return b.Pkg.closureStub(b, t, v)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package ssa
|
|||||||
import (
|
import (
|
||||||
"go/token"
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
@@ -203,7 +204,10 @@ type Program = *aProgram
|
|||||||
// NewProgram creates a new program.
|
// NewProgram creates a new program.
|
||||||
func NewProgram(target *Target) Program {
|
func NewProgram(target *Target) Program {
|
||||||
if target == nil {
|
if target == nil {
|
||||||
target = &Target{}
|
target = &Target{
|
||||||
|
GOOS: runtime.GOOS,
|
||||||
|
GOARCH: runtime.GOARCH,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ctx := llvm.NewContext()
|
ctx := llvm.NewContext()
|
||||||
td := target.targetData() // TODO(xsw): target config
|
td := target.targetData() // TODO(xsw): target config
|
||||||
@@ -604,7 +608,7 @@ const (
|
|||||||
closureStub = "__llgo_stub."
|
closureStub = "__llgo_stub."
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p Package) closureStub(b Builder, t *types.Struct, v Expr) Expr {
|
func (p Package) closureStub(b Builder, t types.Type, v Expr) Expr {
|
||||||
name := v.impl.Name()
|
name := v.impl.Name()
|
||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
nilVal := prog.Nil(prog.VoidPtr()).impl
|
nilVal := prog.Nil(prog.VoidPtr()).impl
|
||||||
|
|||||||
@@ -521,3 +521,34 @@ func TestBasicType(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCompareSelect(t *testing.T) {
|
||||||
|
prog := NewProgram(nil)
|
||||||
|
pkg := prog.NewPackage("bar", "foo/bar")
|
||||||
|
|
||||||
|
params := types.NewTuple(
|
||||||
|
types.NewVar(0, nil, "a", types.Typ[types.Int]),
|
||||||
|
types.NewVar(0, nil, "b", types.Typ[types.Int]),
|
||||||
|
types.NewVar(0, nil, "c", types.Typ[types.Int]),
|
||||||
|
)
|
||||||
|
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int]))
|
||||||
|
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
||||||
|
fn := pkg.NewFunc("fn", sig, InGo)
|
||||||
|
|
||||||
|
b := fn.MakeBody(1)
|
||||||
|
result := b.compareSelect(token.GTR, fn.Param(0), fn.Param(1), fn.Param(2))
|
||||||
|
b.Return(result)
|
||||||
|
|
||||||
|
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
||||||
|
source_filename = "foo/bar"
|
||||||
|
|
||||||
|
define i64 @fn(i64 %0, i64 %1, i64 %2) {
|
||||||
|
_llgo_0:
|
||||||
|
%3 = icmp sgt i64 %0, %1
|
||||||
|
%4 = select i1 %3, i64 %0, i64 %1
|
||||||
|
%5 = icmp sgt i64 %4, %2
|
||||||
|
%6 = select i1 %5, i64 %4, i64 %2
|
||||||
|
ret i64 %6
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|||||||
0
xtool/env/build.go → x/env/build.go
vendored
0
xtool/env/build.go → x/env/build.go
vendored
0
xtool/env/version.go → x/env/version.go
vendored
0
xtool/env/version.go → x/env/version.go
vendored
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user