func floatCmp(x, y Float) int {
	if x > y {
		return +1
	} else if x < y {
		return -1
	} else if x == y {
		return 0
	}
	if x == x {
		return -1  
	} else if y == y {
		return +1  
	}
	return 0  
}
floatCmp performs a three-valued comparison on floats,
which are totally ordered with NaN > +Inf.
package starlark  
import (
	"fmt"
	"math"
	"math/big"
	"reflect"
	"strconv"
	"strings"
	"unicode/utf8"
	"go.starlark.net/internal/compile"
	"go.starlark.net/syntax"
)
type Value interface {
	String() string
	Type() string
	Freeze()
	Truth() Bool
	Hash() (uint32, error)
}
type Comparable interface {
	Value
	CompareSameType(op syntax.Token, y Value, depth int) (bool, error)
}
var (
	_ Comparable = Int{}
	_ Comparable = False
	_ Comparable = Float(0)
	_ Comparable = String("")
	_ Comparable = (*Dict)(nil)
	_ Comparable = (*List)(nil)
	_ Comparable = Tuple(nil)
	_ Comparable = (*Set)(nil)
)
type Callable interface {
	Value
	Name() string
	CallInternal(thread *Thread, args Tuple, kwargs []Tuple) (Value, error)
}
type callableWithPosition interface {
	Callable
	Position() syntax.Position
}
var (
	_ Callable             = (*Builtin)(nil)
	_ Callable             = (*Function)(nil)
	_ callableWithPosition = (*Function)(nil)
)
type Iterable interface {
	Value
	Iterate() Iterator  
}
type Sequence interface {
	Iterable
	Len() int
}
var (
	_ Sequence = (*Dict)(nil)
	_ Sequence = (*Set)(nil)
)
type Indexable interface {
	Value
	Index(i int) Value  
	Len() int
}
type Sliceable interface {
	Indexable
	Slice(start, end, step int) Value
}
type HasSetIndex interface {
	Indexable
	SetIndex(index int, v Value) error
}
var (
	_ HasSetIndex = (*List)(nil)
	_ Indexable   = Tuple(nil)
	_ Indexable   = String("")
	_ Sliceable   = Tuple(nil)
	_ Sliceable   = String("")
	_ Sliceable   = (*List)(nil)
)
type Iterator interface {
	Next(p *Value) bool
	Done()
}
type Mapping interface {
	Value
	Get(Value) (v Value, found bool, err error)
}
type IterableMapping interface {
	Mapping
	Iterate() Iterator  
	Items() []Tuple     
}
var _ IterableMapping = (*Dict)(nil)
type HasSetKey interface {
	Mapping
	SetKey(k, v Value) error
}
var _ HasSetKey = (*Dict)(nil)
type HasBinary interface {
	Value
	Binary(op syntax.Token, y Value, side Side) (Value, error)
}
type Side bool
const (
	Left  Side = false
	Right Side = true
)
type HasUnary interface {
	Value
	Unary(op syntax.Token) (Value, error)
}
type HasAttrs interface {
	Value
	Attr(name string) (Value, error)  
	AttrNames() []string              
}
var (
	_ HasAttrs = String("")
	_ HasAttrs = new(List)
	_ HasAttrs = new(Dict)
	_ HasAttrs = new(Set)
)
type HasSetField interface {
	HasAttrs
	SetField(name string, val Value) error
}
type NoSuchAttrError string
func (e NoSuchAttrError) Error() string { return string(e) }
type NoneType byte
const None = NoneType(0)
func (NoneType) String() string        { return "None" }
func (NoneType) Type() string          { return "NoneType" }
func (NoneType) Freeze()               {}  
func (NoneType) Truth() Bool           { return False }
func (NoneType) Hash() (uint32, error) { return 0, nil }
type Bool bool
const (
	False Bool = false
	True  Bool = true
)
func (b Bool) String() string {
	if b {
		return "True"
	} else {
		return "False"
	}
}
func (b Bool) Type() string          { return "bool" }
func (b Bool) Freeze()               {}  
func (b Bool) Truth() Bool           { return b }
func (b Bool) Hash() (uint32, error) { return uint32(b2i(bool(b))), nil }
func (x Bool) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error) {
	y := y_.(Bool)
	return threeway(op, b2i(bool(x))-b2i(bool(y))), nil
}
type Float float64
func (f Float) String() string {
	var buf strings.Builder
	f.format(&buf, 'g')
	return buf.String()
}
func (f Float) format(buf *strings.Builder, conv byte) {
	ff := float64(f)
	if !isFinite(ff) {
		if math.IsInf(ff, +1) {
			buf.WriteString("+inf")
		} else if math.IsInf(ff, -1) {
			buf.WriteString("-inf")
		} else {
			buf.WriteString("nan")
		}
		return
	}
	if conv == 'g' || conv == 'G' {
		s := strconv.FormatFloat(ff, conv, -1, 64)
		buf.WriteString(s)
		if strings.IndexByte(s, conv-'g'+'e') < 0 && strings.IndexByte(s, '.') < 0 {
			buf.WriteString(".0")
		}
		return
	}
	buf.WriteString(strconv.FormatFloat(ff, conv, 6, 64))
}
func (f Float) Type() string { return "float" }
func (f Float) Freeze()      {}  
func (f Float) Truth() Bool  { return f != 0.0 }
func (f Float) Hash() (uint32, error) {
	if isFinite(float64(f)) {
		return finiteFloatToInt(f).Hash()
	}
	return 1618033, nil  
}
func floor(f Float) Float { return Float(math.Floor(float64(f))) }
func isFinite(f float64) bool {
	return math.Abs(f) <= math.MaxFloat64
}
func (x Float) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error) {
	y := y_.(Float)
	return threeway(op, floatCmp(x, y)), nil
}