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:
James Shubin
2021-05-12 03:28:19 -04:00
parent fe2b8c9fee
commit b3d1ed9e65
5 changed files with 86 additions and 0 deletions

View File

@@ -379,6 +379,14 @@ func (obj *PrintfFunc) Close() error {
// valueToString prints our values how we expect for printf. // valueToString prints our values how we expect for printf.
// FIXME: if this turns out to be useful, add it to the types package. // FIXME: if this turns out to be useful, add it to the types package.
func valueToString(value types.Value) string { 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... // FIXME: this is just an "easy-out" implementation for now...
return fmt.Sprintf("%v", value.Value()) return fmt.Sprintf("%v", value.Value())

View 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)
}

View File

@@ -0,0 +1,2 @@
Vertex: test[float: 42]
Vertex: test[int: 42]

View 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()) {}

View File

@@ -708,6 +708,7 @@ func NewFloat() *FloatValue { return &FloatValue{} }
// String returns a visual representation of this value. // String returns a visual representation of this value.
func (obj *FloatValue) String() string { func (obj *FloatValue) String() string {
// TODO: is this the right display mode? // 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 return strconv.FormatFloat(obj.V, 'f', -1, 64) // -1 for exact precision
} }