lang: funcs: Add math pow function and a few examples
Just a few small things I think should be committed.
This commit is contained in:
@@ -291,7 +291,7 @@ If you'd like to create a built-in, core function, you'll need to implement the
|
||||
function API interface named `Func`. It can be found in
|
||||
[lang/interfaces/func.go](https://github.com/purpleidea/mgmt/tree/master/lang/interfaces/func.go).
|
||||
Your function must have a specific type. For example, a simple math function
|
||||
might have a signature of `func(x int, x int) int`. As you can see, all the
|
||||
might have a signature of `func(x int, y int) int`. As you can see, all the
|
||||
types are known _before_ compile time.
|
||||
|
||||
A separate discussion on this matter can be found in the [function guide](function-guide.md).
|
||||
|
||||
10
examples/lang/env1.mcl
Normal file
10
examples/lang/env1.mcl
Normal file
@@ -0,0 +1,10 @@
|
||||
$env = env()
|
||||
$m = maplookup($env, "GOPATH", "")
|
||||
|
||||
print "print0" {
|
||||
msg => if hasenv("GOPATH") {
|
||||
printf("GOPATH is: %s", $m)
|
||||
} else {
|
||||
"GOPATH is missing!"
|
||||
},
|
||||
}
|
||||
3
examples/lang/math2.mcl
Normal file
3
examples/lang/math2.mcl
Normal file
@@ -0,0 +1,3 @@
|
||||
print "print0" {
|
||||
msg => printf("13.0 ^ 4.2 is: %f", pow(13.0, 4.2)),
|
||||
}
|
||||
3
examples/lang/pkg1.mcl
Normal file
3
examples/lang/pkg1.mcl
Normal file
@@ -0,0 +1,3 @@
|
||||
pkg "cowsay" {
|
||||
state => "installed",
|
||||
}
|
||||
53
lang/funcs/simple/math_func.go
Normal file
53
lang/funcs/simple/math_func.go
Normal file
@@ -0,0 +1,53 @@
|
||||
// Mgmt
|
||||
// Copyright (C) 2013-2018+ James Shubin and the project contributors
|
||||
// Written by James Shubin <james@shubin.ca> and the project contributors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package simple // TODO: should this be in its own individual package?
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/purpleidea/mgmt/lang/types"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Register("pow", &types.FuncValue{
|
||||
T: types.NewType("func(x float, y float) float"),
|
||||
V: Pow,
|
||||
})
|
||||
}
|
||||
|
||||
// Pow returns x ^ y, the base-x exponential of y.
|
||||
func Pow(input []types.Value) (types.Value, error) {
|
||||
x, y := input[0].Float(), input[1].Float()
|
||||
// FIXME: check for overflow
|
||||
z := math.Pow(x, y)
|
||||
if math.IsNaN(z) {
|
||||
return nil, fmt.Errorf("result is not a number")
|
||||
}
|
||||
if math.IsInf(z, 1) {
|
||||
return nil, fmt.Errorf("result is positive infinity")
|
||||
}
|
||||
if math.IsInf(z, -1) {
|
||||
return nil, fmt.Errorf("result is negative infinity")
|
||||
}
|
||||
// TODO: consider only returning floats, and adding isinf and
|
||||
// isnan functions so that users can decide for themselves...
|
||||
return &types.FloatValue{
|
||||
V: z,
|
||||
}, nil
|
||||
}
|
||||
@@ -80,7 +80,7 @@ func TestLexParse0(t *testing.T) {
|
||||
values = append(values, test{
|
||||
name: "bad escaping",
|
||||
code: `
|
||||
test "n1" {
|
||||
test "t1" {
|
||||
str => "he\ llo", # incorrect escaping
|
||||
}
|
||||
`,
|
||||
@@ -91,7 +91,7 @@ func TestLexParse0(t *testing.T) {
|
||||
values = append(values, test{
|
||||
name: "int overflow",
|
||||
code: `
|
||||
test "n1" {
|
||||
test "t1" {
|
||||
int => 888888888888888888888888, # overflows
|
||||
}
|
||||
`,
|
||||
@@ -102,7 +102,7 @@ func TestLexParse0(t *testing.T) {
|
||||
values = append(values, test{
|
||||
name: "overflow after lexer",
|
||||
code: `
|
||||
test "n1" {
|
||||
test "t1" {
|
||||
uint8 => 128, # does not overflow at lexer stage
|
||||
}
|
||||
`,
|
||||
@@ -114,7 +114,7 @@ func TestLexParse0(t *testing.T) {
|
||||
values = append(values, test{
|
||||
name: "one res",
|
||||
code: `
|
||||
test "n1" {
|
||||
test "t1" {
|
||||
int16 => 01134, # some comment
|
||||
}
|
||||
`,
|
||||
@@ -262,7 +262,7 @@ func TestLexParse0(t *testing.T) {
|
||||
values = append(values, test{
|
||||
name: "res with floats",
|
||||
code: `
|
||||
test "n1" {
|
||||
test "t1" {
|
||||
float32 => -25.38789, # some float
|
||||
float64 => 53.393908945, # some float
|
||||
}
|
||||
@@ -279,7 +279,7 @@ func TestLexParse0(t *testing.T) {
|
||||
// values = append(values, test{
|
||||
// name: "overflowing float",
|
||||
// code: `
|
||||
// test "n1" {
|
||||
// test "t1" {
|
||||
// float32 => -457643875645764387564578645457864525457643875645764387564578645457864525.457643875645764387564578645457864525387899898753459879587574928798759863965, # overflow
|
||||
// }
|
||||
// `,
|
||||
@@ -290,7 +290,7 @@ func TestLexParse0(t *testing.T) {
|
||||
values = append(values, test{
|
||||
name: "res and addition",
|
||||
code: `
|
||||
test "n1" {
|
||||
test "t1" {
|
||||
float32 => -25.38789 + 32.6,
|
||||
}
|
||||
`,
|
||||
@@ -304,7 +304,7 @@ func TestLexParse0(t *testing.T) {
|
||||
&StmtRes{
|
||||
Kind: "test",
|
||||
Name: &ExprStr{
|
||||
V: "n1",
|
||||
V: "t1",
|
||||
},
|
||||
Fields: []*StmtResField{
|
||||
{
|
||||
@@ -331,7 +331,7 @@ func TestLexParse0(t *testing.T) {
|
||||
values = append(values, test{
|
||||
name: "addition",
|
||||
code: `
|
||||
test "n1" {
|
||||
test "t1" {
|
||||
int64ptr => 13 + 42,
|
||||
}
|
||||
`,
|
||||
@@ -345,7 +345,7 @@ func TestLexParse0(t *testing.T) {
|
||||
&StmtRes{
|
||||
Kind: "test",
|
||||
Name: &ExprStr{
|
||||
V: "n1",
|
||||
V: "t1",
|
||||
},
|
||||
Fields: []*StmtResField{
|
||||
{
|
||||
@@ -383,7 +383,7 @@ func TestLexParse0(t *testing.T) {
|
||||
values = append(values, test{
|
||||
name: "multiple float addition",
|
||||
code: `
|
||||
test "n1" {
|
||||
test "t1" {
|
||||
float32 => -25.38789 + 32.6 + 13.7,
|
||||
}
|
||||
`,
|
||||
@@ -397,7 +397,7 @@ func TestLexParse0(t *testing.T) {
|
||||
&StmtRes{
|
||||
Kind: "test",
|
||||
Name: &ExprStr{
|
||||
V: "n1",
|
||||
V: "t1",
|
||||
},
|
||||
Fields: []*StmtResField{
|
||||
{
|
||||
@@ -435,7 +435,7 @@ func TestLexParse0(t *testing.T) {
|
||||
values = append(values, test{
|
||||
name: "order of operations lucky",
|
||||
code: `
|
||||
test "n1" {
|
||||
test "t1" {
|
||||
int64ptr => 4 + 3 * 12, # 40, not 84
|
||||
}
|
||||
`,
|
||||
@@ -449,7 +449,7 @@ func TestLexParse0(t *testing.T) {
|
||||
&StmtRes{
|
||||
Kind: "test",
|
||||
Name: &ExprStr{
|
||||
V: "n1",
|
||||
V: "t1",
|
||||
},
|
||||
Fields: []*StmtResField{
|
||||
{
|
||||
@@ -487,7 +487,7 @@ func TestLexParse0(t *testing.T) {
|
||||
values = append(values, test{
|
||||
name: "order of operations needs left precedence",
|
||||
code: `
|
||||
test "n1" {
|
||||
test "t1" {
|
||||
int64ptr => 3 * 12 + 4, # 40, not 48
|
||||
}
|
||||
`,
|
||||
@@ -501,7 +501,7 @@ func TestLexParse0(t *testing.T) {
|
||||
&StmtRes{
|
||||
Kind: "test",
|
||||
Name: &ExprStr{
|
||||
V: "n1",
|
||||
V: "t1",
|
||||
},
|
||||
Fields: []*StmtResField{
|
||||
{
|
||||
@@ -539,7 +539,7 @@ func TestLexParse0(t *testing.T) {
|
||||
values = append(values, test{
|
||||
name: "order of operations parens",
|
||||
code: `
|
||||
test "n1" {
|
||||
test "t1" {
|
||||
int64ptr => 3 * (12 + 4), # 48, not 40
|
||||
}
|
||||
`,
|
||||
@@ -553,7 +553,7 @@ func TestLexParse0(t *testing.T) {
|
||||
&StmtRes{
|
||||
Kind: "test",
|
||||
Name: &ExprStr{
|
||||
V: "n1",
|
||||
V: "t1",
|
||||
},
|
||||
Fields: []*StmtResField{
|
||||
{
|
||||
@@ -591,7 +591,7 @@ func TestLexParse0(t *testing.T) {
|
||||
values = append(values, test{
|
||||
name: "order of operations bools",
|
||||
code: `
|
||||
test "n1" {
|
||||
test "t1" {
|
||||
boolptr => 3 + 4 > 5, # should be true
|
||||
}
|
||||
`,
|
||||
@@ -605,7 +605,7 @@ func TestLexParse0(t *testing.T) {
|
||||
&StmtRes{
|
||||
Kind: "test",
|
||||
Name: &ExprStr{
|
||||
V: "n1",
|
||||
V: "t1",
|
||||
},
|
||||
Fields: []*StmtResField{
|
||||
{
|
||||
@@ -643,7 +643,7 @@ func TestLexParse0(t *testing.T) {
|
||||
values = append(values, test{
|
||||
name: "order of operations bools reversed",
|
||||
code: `
|
||||
test "n1" {
|
||||
test "t1" {
|
||||
boolptr => 3 > 4 + 5, # should be false
|
||||
}
|
||||
`,
|
||||
@@ -657,7 +657,7 @@ func TestLexParse0(t *testing.T) {
|
||||
&StmtRes{
|
||||
Kind: "test",
|
||||
Name: &ExprStr{
|
||||
V: "n1",
|
||||
V: "t1",
|
||||
},
|
||||
Fields: []*StmtResField{
|
||||
{
|
||||
@@ -692,7 +692,7 @@ func TestLexParse0(t *testing.T) {
|
||||
values = append(values, test{
|
||||
name: "order of operations with not",
|
||||
code: `
|
||||
test "n1" {
|
||||
test "t1" {
|
||||
boolptr => ! 3 > 4, # should parse, but not compile
|
||||
}
|
||||
`,
|
||||
@@ -706,7 +706,7 @@ func TestLexParse0(t *testing.T) {
|
||||
&StmtRes{
|
||||
Kind: "test",
|
||||
Name: &ExprStr{
|
||||
V: "n1",
|
||||
V: "t1",
|
||||
},
|
||||
Fields: []*StmtResField{
|
||||
{
|
||||
@@ -744,7 +744,7 @@ func TestLexParse0(t *testing.T) {
|
||||
values = append(values, test{
|
||||
name: "order of operations logical",
|
||||
code: `
|
||||
test "n1" {
|
||||
test "t1" {
|
||||
boolptr => 7 < 4 && true, # should be false
|
||||
}
|
||||
`,
|
||||
@@ -879,7 +879,7 @@ func TestLexParse1(t *testing.T) {
|
||||
}
|
||||
# hello
|
||||
# world
|
||||
test "n1" {}
|
||||
test "t1" {}
|
||||
` // error
|
||||
str := strings.NewReader(code)
|
||||
_, err := LexParse(str)
|
||||
|
||||
2
test.sh
2
test.sh
@@ -89,7 +89,7 @@ if [[ -n "$failures" ]]; then
|
||||
echo
|
||||
echo 'You can rerun a single suite like so:'
|
||||
echo
|
||||
echo 'make test-gofmt'
|
||||
echo '`make test-gofmt` or `make test-shell-<testname>`'
|
||||
exit 1
|
||||
fi
|
||||
echo 'ALL PASSED'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "running test-gotest.sh $1"
|
||||
echo running "$0" "$@"
|
||||
|
||||
#ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )" # dir!
|
||||
ROOT=$(dirname "${BASH_SOURCE}")/..
|
||||
|
||||
Reference in New Issue
Block a user