Skip to content

Commit

Permalink
Add ceil(), floor() and round() function
Browse files Browse the repository at this point in the history
Fixes #476
  • Loading branch information
antonmedv committed Nov 24, 2023
1 parent 281d598 commit ad0e877
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 0 deletions.
42 changes: 42 additions & 0 deletions builtin/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,48 @@ var Builtins = []*ast.Function{
return anyType, fmt.Errorf("invalid argument for abs (type %s)", args[0])
},
},
{
Name: "ceil",
Fast: Ceil,
Validate: func(args []reflect.Type) (reflect.Type, error) {
if len(args) != 1 {
return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
}
switch kind(args[0]) {
case reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Interface:
return floatType, nil
}
return anyType, fmt.Errorf("invalid argument for ceil (type %s)", args[0])
},
},
{
Name: "floor",
Fast: Floor,
Validate: func(args []reflect.Type) (reflect.Type, error) {
if len(args) != 1 {
return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
}
switch kind(args[0]) {
case reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Interface:
return floatType, nil
}
return anyType, fmt.Errorf("invalid argument for floor (type %s)", args[0])
},
},
{
Name: "round",
Fast: Round,
Validate: func(args []reflect.Type) (reflect.Type, error) {
if len(args) != 1 {
return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
}
switch kind(args[0]) {
case reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Interface:
return floatType, nil
}
return anyType, fmt.Errorf("invalid argument for floor (type %s)", args[0])
},
},
{
Name: "int",
Fast: Int,
Expand Down
7 changes: 7 additions & 0 deletions builtin/builtin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ func TestBuiltin(t *testing.T) {
{`abs(-5)`, 5},
{`abs(.5)`, .5},
{`abs(-.5)`, .5},
{`ceil(5.5)`, 6.0},
{`ceil(5)`, 5.0},
{`floor(5.5)`, 5.0},
{`floor(5)`, 5.0},
{`round(5.5)`, 6.0},
{`round(5)`, 5.0},
{`round(5.49)`, 5.0},
{`int(5.5)`, 5},
{`int(5)`, 5},
{`int("5")`, 5},
Expand Down
37 changes: 37 additions & 0 deletions builtin/func.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package builtin

import (
"fmt"
"math"
"reflect"
"strconv"

Expand Down Expand Up @@ -138,6 +139,42 @@ func Abs(x any) any {
panic(fmt.Sprintf("invalid argument for abs (type %T)", x))
}

func Ceil(x any) any {
switch x := x.(type) {
case float32:
return math.Ceil(float64(x))
case float64:
return math.Ceil(x)
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
return Float(x)
}
panic(fmt.Sprintf("invalid argument for ceil (type %T)", x))
}

func Floor(x any) any {
switch x := x.(type) {
case float32:
return math.Floor(float64(x))
case float64:
return math.Floor(x)
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
return Float(x)
}
panic(fmt.Sprintf("invalid argument for floor (type %T)", x))
}

func Round(x any) any {
switch x := x.(type) {
case float32:
return math.Round(float64(x))
case float64:
return math.Round(x)
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
return Float(x)
}
panic(fmt.Sprintf("invalid argument for round (type %T)", x))
}

func Int(x any) any {
switch x := x.(type) {
case float32:
Expand Down
24 changes: 24 additions & 0 deletions docs/Language-Definition.md
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,30 @@ min(5, 7) == 5

Returns the absolute value of a number.

### ceil(n)

Returns the least integer value greater than or equal to x.

```expr
ceil(1.5) == 2.0
```

### floor(n)

Returns the greatest integer value less than or equal to x.

```expr
floor(1.5) == 1.0
```

### round(n)

Returns the nearest integer, rounding half away from zero.

```expr
round(1.5) == 2.0
```

## Array Functions

### all(array, predicate)
Expand Down

0 comments on commit ad0e877

Please sign in to comment.