1
1
mirror of https://github.com/wader/fq.git synced 2024-12-24 22:05:31 +03:00

Merge pull request #61 from wader/bitops-funcs

interp,fq: Make bit operators normal functions
This commit is contained in:
Mattias Wadman 2022-01-09 01:10:45 +01:00 committed by GitHub
commit 2743585219
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 157 additions and 3 deletions

2
go.mod
View File

@ -23,7 +23,7 @@ require (
require (
// fork of github.com/itchyny/gojq, see github.com/wader/gojq fq branch
github.com/wader/gojq v0.12.1-0.20211211101122-3894ded312be
github.com/wader/gojq v0.12.1-0.20220108235115-6a05b6c59ace
// fork of github.com/chzyer/readline, see github.com/wader/readline fq branch
github.com/wader/readline v0.0.0-20210920124728-5a81f7707bac
)

4
go.sum
View File

@ -16,8 +16,8 @@ github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJ
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/wader/gojq v0.12.1-0.20211211101122-3894ded312be h1:Bc8ZRZxUqQPPwHqdY1c99mKInhJ0UeWEMjgsjHMRGUA=
github.com/wader/gojq v0.12.1-0.20211211101122-3894ded312be/go.mod h1:tdC5h6dXdwAJs7eJUw4681AzsgfOSBrAV+cZzEbCZs4=
github.com/wader/gojq v0.12.1-0.20220108235115-6a05b6c59ace h1:pt07NaC7OhePrQVRKRxZy9umeWkjr28AmbtQC9CrtVQ=
github.com/wader/gojq v0.12.1-0.20220108235115-6a05b6c59ace/go.mod h1:tdC5h6dXdwAJs7eJUw4681AzsgfOSBrAV+cZzEbCZs4=
github.com/wader/readline v0.0.0-20210920124728-5a81f7707bac h1:F5x54dwg6vGyf+8XhujiyXr651E3tKpcL1mqGmS7/MU=
github.com/wader/readline v0.0.0-20210920124728-5a81f7707bac/go.mod h1:jYXyt9wQg3DifxQ8FM5M/ZoskO23GIwmo05QLHtO9CQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=

View File

@ -11,6 +11,24 @@ import (
// TODO: refactor to use errors from gojq?
// TODO: preview from gojq?
type UnaryTypeError struct {
Name string
V interface{}
}
func (err *UnaryTypeError) Error() string {
return fmt.Sprintf("cannot %s: %s", err.Name, typeof(err.V))
}
type BinopTypeError struct {
Name string
L, R interface{}
}
func (err *BinopTypeError) Error() string {
return "cannot " + err.Name + ": " + typeof(err.L) + " and " + typeof(err.R)
}
type NonUpdatableTypeError struct {
Typ string
Key string

109
pkg/interp/bitops.go Normal file
View File

@ -0,0 +1,109 @@
package interp
import (
"math/big"
"github.com/wader/fq/internal/gojqextra"
"github.com/wader/gojq"
)
func init() {
functionRegisterFns = append(functionRegisterFns, func(i *Interp) []Function {
return []Function{
{"bnot", 0, 0, i.bnot, nil},
{"bsl", 2, 2, i.bsl, nil},
{"bsr", 2, 2, i.bsr, nil},
{"band", 2, 2, i.band, nil},
{"bor", 2, 2, i.bor, nil},
{"bxor", 2, 2, i.bxor, nil},
}
})
}
func (i *Interp) bnot(c interface{}, a []interface{}) interface{} {
switch c := c.(type) {
case int:
return ^c
case *big.Int:
return new(big.Int).Not(c)
case gojq.JQValue:
return i.bnot(c.JQValueToGoJQ(), a)
default:
return &gojqextra.UnaryTypeError{Name: "bnot", V: c}
}
}
func (i *Interp) bsl(c interface{}, a []interface{}) interface{} {
return gojq.BinopTypeSwitch(a[0], a[1],
func(l, r int) bool { return false }, // TODO: can be int safe i think
func(l, r int) interface{} { return l << r },
func(l, r float64) interface{} { return int(l) << int(r) },
func(l, r *big.Int) interface{} { return new(big.Int).Lsh(l, uint(r.Uint64())) },
func(l, r string) interface{} { return &gojqextra.BinopTypeError{Name: "bsl", L: l, R: r} },
func(l, r []interface{}) interface{} { return &gojqextra.BinopTypeError{Name: "bsl", L: l, R: r} },
func(l, r map[string]interface{}) interface{} {
return &gojqextra.BinopTypeError{Name: "bsl", L: l, R: r}
},
func(l, r interface{}) interface{} { return &gojqextra.BinopTypeError{Name: "bsl", L: l, R: r} },
)
}
func (i *Interp) bsr(c interface{}, a []interface{}) interface{} {
return gojq.BinopTypeSwitch(a[0], a[1],
func(l, r int) bool { return true },
func(l, r int) interface{} { return l >> r },
func(l, r float64) interface{} { return int(l) >> int(r) },
func(l, r *big.Int) interface{} { return new(big.Int).Rsh(l, uint(r.Uint64())) },
func(l, r string) interface{} { return &gojqextra.BinopTypeError{Name: "bsr", L: l, R: r} },
func(l, r []interface{}) interface{} { return &gojqextra.BinopTypeError{Name: "bsr", L: l, R: r} },
func(l, r map[string]interface{}) interface{} {
return &gojqextra.BinopTypeError{Name: "bsr", L: l, R: r}
},
func(l, r interface{}) interface{} { return &gojqextra.BinopTypeError{Name: "bsr", L: l, R: r} },
)
}
func (i *Interp) band(c interface{}, a []interface{}) interface{} {
return gojq.BinopTypeSwitch(a[0], a[1],
func(l, r int) bool { return true },
func(l, r int) interface{} { return l & r },
func(l, r float64) interface{} { return int(l) & int(r) },
func(l, r *big.Int) interface{} { return new(big.Int).And(l, r) },
func(l, r string) interface{} { return &gojqextra.BinopTypeError{Name: "band", L: l, R: r} },
func(l, r []interface{}) interface{} { return &gojqextra.BinopTypeError{Name: "band", L: l, R: r} },
func(l, r map[string]interface{}) interface{} {
return &gojqextra.BinopTypeError{Name: "band", L: l, R: r}
},
func(l, r interface{}) interface{} { return &gojqextra.BinopTypeError{Name: "band", L: l, R: r} },
)
}
func (i *Interp) bor(c interface{}, a []interface{}) interface{} {
return gojq.BinopTypeSwitch(a[0], a[1],
func(l, r int) bool { return true },
func(l, r int) interface{} { return l | r },
func(l, r float64) interface{} { return int(l) | int(r) },
func(l, r *big.Int) interface{} { return new(big.Int).Or(l, r) },
func(l, r string) interface{} { return &gojqextra.BinopTypeError{Name: "bor", L: l, R: r} },
func(l, r []interface{}) interface{} { return &gojqextra.BinopTypeError{Name: "bor", L: l, R: r} },
func(l, r map[string]interface{}) interface{} {
return &gojqextra.BinopTypeError{Name: "bor", L: l, R: r}
},
func(l, r interface{}) interface{} { return &gojqextra.BinopTypeError{Name: "bor", L: l, R: r} },
)
}
func (i *Interp) bxor(c interface{}, a []interface{}) interface{} {
return gojq.BinopTypeSwitch(a[0], a[1],
func(l, r int) bool { return true },
func(l, r int) interface{} { return l ^ r },
func(l, r float64) interface{} { return int(l) ^ int(r) },
func(l, r *big.Int) interface{} { return new(big.Int).Xor(l, r) },
func(l, r string) interface{} { return &gojqextra.BinopTypeError{Name: "bxor", L: l, R: r} },
func(l, r []interface{}) interface{} { return &gojqextra.BinopTypeError{Name: "bxor", L: l, R: r} },
func(l, r map[string]interface{}) interface{} {
return &gojqextra.BinopTypeError{Name: "bxor", L: l, R: r}
},
func(l, r interface{}) interface{} { return &gojqextra.BinopTypeError{Name: "bxor", L: l, R: r} },
)
}

27
pkg/interp/testdata/bitops.fqtest vendored Normal file
View File

@ -0,0 +1,27 @@
$ fq -i
null> 0, -1, 1208925819614629174706175, -1208925819614629174706176 | bnot
-1
0
-1208925819614629174706176
1208925819614629174706175
null> [0,0], [8,1], [0xffff_ffff_ffff_ffff,1] | bsl(.[0]; .[1])
0
16
36893488147419103230
null> [0,0], [8,1], [0x1_ffff_ffff_ffff_fffe,1] | bsr(.[0]; .[1])
0
4
18446744073709551615
null> [0,0], [0xffff_ffff_ffff_ffff_ffff,0x1234], [0x1234,0xffff_ffff_ffff_ffff_ffff,0x1234] | band(.[0]; .[1])
0
4660
4660
null> [0,0], [0xffff_ffff_ffff_ffff_0000,0x1234], [0x1234,0xffff_ffff_ffff_ffff_0000,0x1234] | bor(.[0]; .[1])
0
1208925819614629174645300
1208925819614629174645300
null> [0,0], [0xffff_ffff_ffff_ffff_ffff,0x1234], [0x1234,0xffff_ffff_ffff_ffff_ffff,0x1234] | bxor(.[0]; .[1])
0
1208925819614629174701515
1208925819614629174701515
null> ^D