diff --git a/main.go b/main.go index 4b6ed33..f79e3a1 100644 --- a/main.go +++ b/main.go @@ -20,7 +20,7 @@ import ( const ( intro = PROGNAME + ` -- Expressions calculator ` + VERSION + ` - Based on the Expr package ` + EXPR_VERSION + ` + Based on the Expr package ` + EXPR_VERSION + ` (` + EXPR_DATE + `) Type help to get the list of available commands See also https://git.portale-stac.it/go-pkg/expr/src/branch/main/README.adoc ` @@ -243,7 +243,8 @@ func isReaderTerminal(r io.Reader) bool { func registerLocalFunctions(ctx expr.ExprContext) { const ( - devParamProp = "prop" + devParamProp = "prop" + devParamDigits = "digits" ) aboutFunc := func(ctx expr.ExprContext, name string, args map[string]any) (result any, err error) { @@ -300,6 +301,46 @@ func registerLocalFunctions(ctx expr.ExprContext) { return } + binFunc := func(ctx expr.ExprContext, name string, args map[string]any) (result any, err error) { + var value, digits int64 + var ok bool + var sb strings.Builder + + if value, ok = args[expr.ParamValue].(int64); !ok { + err = expr.ErrExpectedGot(name, expr.TypeInt, args[expr.ParamValue]) + return + } + if digits, ok = args[devParamDigits].(int64); !ok { + err = expr.ErrExpectedGot(name, expr.TypeInt, args[devParamDigits]) + return + } + if digits != 64 && digits != 32 && digits != 16 && digits != 8 { + err = fmt.Errorf("%s param allows 8, 16, 32, or 64 values only", devParamDigits) + return + } + + mask := uint64(0) + for i := 0; i < int(digits); i++ { + mask |= (1 << i) + } + maskedValue := uint64(value) & mask + // if maskedValue != uint64(value) { + // err = fmt.Errorf("%s param (%d) is not compatible with the value (%d) of %s param", expr.ParamValue, value, digits, devParamDigits) + // return + // } + + for i := int(digits) - 1; i >= 0; i-- { + if maskedValue&(1<