lang: funcs: core: math: Add a fortytwo function
This is mainly meant as a useful test case, but might as well have it be fun too. As an aside, it taught me a surprising result about the %v verb in printf, and we'll have to decide if it's an issue we care about. https://github.com/golang/go/issues/46118 The interesting thing about this method is that it uses the simplepoly API but has no input args-- only the output types are different. If it had identical types in the input args, that might also have been interesting, but it's more rare to have none. Hopefully this exercises our type unification logic.
This commit is contained in:
@@ -379,6 +379,14 @@ func (obj *PrintfFunc) Close() error {
|
||||
// valueToString prints our values how we expect for printf.
|
||||
// FIXME: if this turns out to be useful, add it to the types package.
|
||||
func valueToString(value types.Value) string {
|
||||
switch x := value.Type().Kind; x {
|
||||
// FIXME: floats don't print nicely: https://github.com/golang/go/issues/46118
|
||||
case types.KindFloat:
|
||||
// TODO: use formatting flags ?
|
||||
// FIXME: Our String() method in FloatValue doesn't print nicely
|
||||
return value.String()
|
||||
}
|
||||
|
||||
// FIXME: this is just an "easy-out" implementation for now...
|
||||
return fmt.Sprintf("%v", value.Value())
|
||||
|
||||
|
||||
69
lang/funcs/core/math/fortytwo_func.go
Normal file
69
lang/funcs/core/math/fortytwo_func.go
Normal file
@@ -0,0 +1,69 @@
|
||||
// Mgmt
|
||||
// Copyright (C) 2013-2021+ 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 coremath
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/purpleidea/mgmt/lang/funcs/simplepoly"
|
||||
"github.com/purpleidea/mgmt/lang/types"
|
||||
)
|
||||
|
||||
func init() {
|
||||
typInt := types.NewType("func() int")
|
||||
typFloat := types.NewType("func() float")
|
||||
simplepoly.ModuleRegister(ModuleName, "fortytwo", []*types.FuncValue{
|
||||
{
|
||||
T: typInt,
|
||||
V: fortyTwo(typInt), // generate the correct function here
|
||||
},
|
||||
{
|
||||
T: typFloat,
|
||||
V: fortyTwo(typFloat),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// fortyTwo is a helper function to build the correct function for the desired
|
||||
// signature, because the simplepoly API doesn't tell the implementing function
|
||||
// what its signature should be! In the next version of this API, we could pass
|
||||
// in a sig field, like how we demonstrate in the implementation of FortyTwo. If
|
||||
// the API doesn't change, then this is an example of how to build this as a
|
||||
// wrapper.
|
||||
func fortyTwo(sig *types.Type) func([]types.Value) (types.Value, error) {
|
||||
return func(input []types.Value) (types.Value, error) {
|
||||
return FortyTwo(sig, input)
|
||||
}
|
||||
}
|
||||
|
||||
// FortyTwo returns 42 as either an int or a float. This is not especially
|
||||
// useful, but was built for a fun test case of a simple poly function with two
|
||||
// different return types, but no input args.
|
||||
func FortyTwo(sig *types.Type, input []types.Value) (types.Value, error) {
|
||||
if sig.Out.Kind == types.KindInt {
|
||||
return &types.IntValue{
|
||||
V: 42,
|
||||
}, nil
|
||||
}
|
||||
if sig.Out.Kind == types.KindFloat {
|
||||
return &types.FloatValue{
|
||||
V: 42.0,
|
||||
}, nil
|
||||
}
|
||||
return nil, fmt.Errorf("unknown output type: %+v", sig.Out)
|
||||
}
|
||||
2
lang/interpret_test/TestAstFunc2/fortytwo.output
Normal file
2
lang/interpret_test/TestAstFunc2/fortytwo.output
Normal file
@@ -0,0 +1,2 @@
|
||||
Vertex: test[float: 42]
|
||||
Vertex: test[int: 42]
|
||||
6
lang/interpret_test/TestAstFunc2/fortytwo/main.mcl
Normal file
6
lang/interpret_test/TestAstFunc2/fortytwo/main.mcl
Normal file
@@ -0,0 +1,6 @@
|
||||
import "fmt"
|
||||
import "math"
|
||||
# FIXME: floats don't print nicely: https://github.com/golang/go/issues/46118
|
||||
# FIXME: This means that we see "42" for both, instead of 42.0 ...
|
||||
test fmt.printf("int: %d", math.fortytwo()) {}
|
||||
test fmt.printf("float: %f", math.fortytwo()) {}
|
||||
@@ -708,6 +708,7 @@ func NewFloat() *FloatValue { return &FloatValue{} }
|
||||
// String returns a visual representation of this value.
|
||||
func (obj *FloatValue) String() string {
|
||||
// TODO: is this the right display mode?
|
||||
// FIXME: floats don't print nicely: https://github.com/golang/go/issues/46118
|
||||
return strconv.FormatFloat(obj.V, 'f', -1, 64) // -1 for exact precision
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user